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) {
339 glTranslatef(cs->steps < 50 ? cs->from[1] : cs->to[1], 0.0,
340 cs->steps < 50 ? cs->from[0] : cs->to[0]);
342 mult = cs->steps < 10
343 ? (1.0 - cs->steps / 10.0) : 100 - cs->steps < 10
344 ? (1.0 - (100 - cs->steps) / 10.0) : 0.0;
346 shine[0] = mult*shininess[0];
347 spec[0] = mult*specular[0];
348 spec[1] = mult*specular[1];
349 spec[2] = mult*specular[2];
351 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine);
352 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
354 glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->mpiece/7][0],
355 shadow ? MaterialShadow[1] : cs->colors[cs->mpiece/7][1],
356 shadow ? MaterialShadow[2] : cs->colors[cs->mpiece/7][2],
357 fabs(49-cs->steps)/49.0);
359 glScalef(fabs(49-cs->steps)/49.0, fabs(49-cs->steps)/49.0, fabs(49-cs->steps)/49.0);
362 glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz);
368 mi->polygon_count += cs->poly_counts[cs->mpiece % PIECES];
370 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
371 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
379 /** code to squish a taken piece */
380 static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow)
385 glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][0],
386 shadow ? MaterialShadow[1] : cs->colors[cs->tpiece/7][1],
387 shadow ? MaterialShadow[2] : cs->colors[cs->tpiece/7][2],
388 (100-1.6*cs->steps)/100.0);
390 glTranslatef(cs->to[1], 0.0, cs->to[0]);
392 if(cs->mpiece % PIECES == KNIGHT)
393 glScalef(1.0+cs->steps/100.0, 1.0, 1.0+cs->steps/100.0);
395 glScalef(1.0, 1 - cs->steps/50.0 > 0.01 ? 1 - cs->steps/50.0 : 0.01, 1.0);
396 glCallList(cs->tpiece % 7);
397 mi->polygon_count += cs->poly_counts[cs->tpiece % PIECES];
404 static void drawBoard(ModeInfo *mi, Chesscreen *cs)
410 for(i = 0; i < BOARDSIZE; ++i)
411 for(j = 0; j < BOARDSIZE; ++j) {
412 double ma1 = (i+j)%2 == 0 ? cs->mod*i : 0.0;
413 double mb1 = (i+j)%2 == 0 ? cs->mod*j : 0.0;
414 double ma2 = (i+j)%2 == 0 ? cs->mod*(i+1.0) : 0.01;
415 double mb2 = (i+j)%2 == 0 ? cs->mod*(j+1.0) : 0.01;
417 /*glColor3fv(colors[(i+j)%2]);*/
418 glColor4f(cs->colors[(i+j)%2][0], cs->colors[(i+j)%2][1],
419 cs->colors[(i+j)%2][2], 0.65);
421 glNormal3f(0.0, 1.0, 0.0);
422 /* glTexCoord2f(mod*i, mod*(j+1.0)); */
423 glTexCoord2f(ma1, mb2);
424 glVertex3f(i, 0.0, j + 1.0);
425 /* glTexCoord2f(mod*(i+1.0), mod*(j+1.0)); */
426 glTexCoord2f(ma2, mb2);
427 glVertex3f(i + 1.0, 0.0, j + 1.0);
428 glTexCoord2f(ma2, mb1);
429 /* glTexCoord2f(mod*(i+1.0), mod*j); */
430 glVertex3f(i + 1.0, 0.0, j);
431 glTexCoord2f(ma1, mb1);
432 /* glTexCoord2f(mod*i, mod*j); */
433 glVertex3f(i, 0.0, j);
438 /* chop underneath board */
439 /* glColor3f(0, 0, 0); */
440 /* glNormal3f(0, -1, 0); */
441 /* glVertex3f(0, 0, BOARDSIZE); */
442 /* glVertex3f(0, 0, 0); */
443 /* glVertex3f(BOARDSIZE, 0, 0); */
444 /* glVertex3f(BOARDSIZE, 0, BOARDSIZE); */
448 static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire)
451 glEnable(GL_TEXTURE_2D);
452 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
453 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
455 glColor4f(0.5, 0.5, 0.5, 1.0);
456 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
460 if(cs->moving) drawMovingPiece(mi, cs, 0);
461 if(cs->take) drawTakePiece(mi, cs, 0);
462 glDisable(GL_TEXTURE_2D);
465 static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire)
468 glEnable(GL_TEXTURE_2D);
469 glBindTexture(GL_TEXTURE_2D, cs->piecetexture);
470 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
473 /* use the stencil */
474 glDisable(GL_LIGHTING);
475 glDisable(GL_COLOR_MATERIAL);
476 glDisable(GL_DEPTH_TEST);
477 glDisable(GL_TEXTURE_2D);
480 glClear(GL_STENCIL_BUFFER_BIT);
481 glColorMask(0,0,0,0);
482 glEnable(GL_STENCIL_TEST);
484 glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL);
485 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
489 glTranslatef(0.0, 0.001, 0.0);
491 /* draw the pieces */
492 drawPiecesShadow(mi, cs);
493 if(cs->moving) drawMovingPiece(mi, cs, shadows);
494 if(cs->take) drawTakePiece(mi, cs, shadows);
499 /* turn on drawing into colour buffer */
500 glColorMask(1,1,1,1);
502 /* programming with effect */
503 glDisable(GL_LIGHTING);
504 glDisable(GL_COLOR_MATERIAL);
505 glDisable(GL_TEXTURE_2D);
507 /* now draw the union of the shadows */
511 want to keep alpha values (alpha is involved in transition
512 effects of the active pieces).
515 glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL);
516 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
520 glColor4fv(MaterialShadow);
522 /* draw the board generously to fill the shadows */
525 glVertex3f(-1.0, 0.0, -1.0);
526 glVertex3f(-1.0, 0.0, BOARDSIZE + 1.0);
527 glVertex3f(1.0 + BOARDSIZE, 0.0, BOARDSIZE + 1.0);
528 glVertex3f(1.0 + BOARDSIZE, 0.0, -1.0);
532 glDisable(GL_STENCIL_TEST);
534 /* "pop" attributes */
535 glEnable(GL_TEXTURE_2D);
536 glEnable(GL_COLOR_MATERIAL);
537 glEnable(GL_LIGHTING);
538 glEnable(GL_CULL_FACE);
547 /* create a matrix that will project the desired shadow */
548 static void shadowmatrix(GLfloat shadowMat[4][4],
549 GLfloat groundplane[4],
554 /* find dot product between light position vector and ground plane normal */
555 dot = groundplane[X] * lightpos[X] +
556 groundplane[Y] * lightpos[Y] +
557 groundplane[Z] * lightpos[Z] +
558 groundplane[W] * lightpos[W];
560 shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
561 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
562 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
563 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
565 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
566 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
567 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
568 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
570 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
571 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
572 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
573 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
575 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
576 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
577 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
578 shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
581 /** reflectionboard */
582 static void draw_reflections(ModeInfo *mi, Chesscreen *cs)
586 glEnable(GL_STENCIL_TEST);
587 glStencilFunc(GL_ALWAYS, 1, 1);
588 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
589 glColorMask(0,0,0,0);
590 glDisable(GL_CULL_FACE);
592 glDisable(GL_DEPTH_TEST);
595 /* only draw white squares */
596 for(i = 0; i < BOARDSIZE; ++i) {
597 for(j = (BOARDSIZE+i) % 2; j < BOARDSIZE; j += 2) {
598 glVertex3f(i, 0.0, j + 1.0);
599 glVertex3f(i + 1.0, 0.0, j + 1.0);
600 glVertex3f(i + 1.0, 0.0, j);
601 glVertex3f(i, 0.0, j);
606 glEnable(GL_DEPTH_TEST);
608 glColorMask(1, 1, 1, 1);
609 glStencilFunc(GL_EQUAL, 1, 1);
610 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
613 glScalef(1.0, -1.0, 1.0);
614 glTranslatef(0.5, 0.0, 0.5);
616 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
617 draw_pieces(mi, cs, cs->wire);
620 glDisable(GL_STENCIL_TEST);
621 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
623 glEnable(GL_CULL_FACE);
625 glColorMask(1,1,1,1);
628 /** draws the scene */
629 static void display(ModeInfo *mi, Chesscreen *cs)
631 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
633 mi->polygon_count = 0;
635 glMatrixMode(GL_MODELVIEW);
637 glRotatef(current_device_rotation(), 0, 0, 1);
639 /** setup perspectiv */
640 glTranslatef(0.0, 0.0, -1.5*BOARDSIZE);
641 glRotatef(30.0, 1.0, 0.0, 0.0);
642 glRotatef(-current_device_rotation(), 0, 0, 1);
643 gltrackball_rotate (cs->trackball);
644 glRotatef(current_device_rotation(), 0, 0, 1);
646 glRotatef(cs->theta*100, 0.0, 1.0, 0.0);
647 glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE);
649 /* cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */
650 /* cs->position[2] = 4.0 + 1.0* cos(cs->theta*100*M_PI/180.0); */
651 /* cs->position[1] = 5.0; */
653 /* this is the lone light that the shadow matrix is generated from */
654 cs->position[0] = 1.0;
655 cs->position[2] = 1.0;
656 cs->position[1] = 16.0;
658 cs->position2[0] = 4.0 + 8.0*-sin(cs->theta*100*M_PI/180.0);
659 cs->position2[2] = 4.0 + 8.0* cos(cs->theta*100*M_PI/180.0);
662 glEnable(GL_LIGHTING);
663 glLightfv(GL_LIGHT0, GL_POSITION, cs->position);
664 glLightfv(GL_LIGHT1, GL_POSITION, cs->position2);
668 /** draw board, pieces */
670 glEnable(GL_LIGHTING);
671 glEnable(GL_COLOR_MATERIAL);
673 if(reflections && !cs->wire) {
674 draw_reflections(mi, cs);
678 glEnable(GL_TEXTURE_2D);
679 glBindTexture(GL_TEXTURE_2D, cs->boardtexture);
681 glDisable(GL_TEXTURE_2D);
686 shadowmatrix(m, cs->ground, cs->position);
688 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow);
690 glDisable(GL_LIGHTING);
691 glDisable(GL_DEPTH_TEST);
693 /* display ant shadow */
695 glTranslatef(0.0, 0.001, 0.0);
697 glTranslatef(0.5, 0.01, 0.5);
698 draw_shadow_pieces(mi, cs, cs->wire);
701 glEnable(GL_LIGHTING);
703 glEnable(GL_DEPTH_TEST);
712 glTranslatef(0.5, 0.0, 0.5);
713 draw_pieces(mi, cs, cs->wire);
716 glDisable(GL_COLOR_MATERIAL);
717 glDisable(GL_LIGHTING);
720 if (!cs->button_down_p)
724 /** reshape handler */
725 ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height)
727 GLfloat h = (GLfloat) height / (GLfloat) width;
728 glViewport(0,0, width, height);
729 glMatrixMode(GL_PROJECTION);
731 gluPerspective(45, 1/h, 2.0, 30.0);
732 glMatrixMode(GL_MODELVIEW);
735 /** initialization handler */
736 ENTRYPOINT void init_chess(ModeInfo *mi)
739 int screen = MI_SCREEN(mi);
742 !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen))))
746 cs->window = MI_WINDOW(mi);
747 cs->wire = MI_IS_WIREFRAME(mi);
748 cs->trackball = gltrackball_init ();
752 cs->colors[0][0] = 1.0;
753 cs->colors[0][1] = 0.5;
754 cs->colors[0][2] = 0.0;
756 cs->colors[1][0] = 0.6;
757 cs->colors[1][1] = 0.6;
758 cs->colors[1][2] = 0.6;
764 /* cs->position[0] = 0.0; */
765 /* cs->position[1] = 5.0; */
766 /* cs->position[2] = 5.0; */
767 /* cs->position[3] = 1.0; */
769 cs->position[0] = 0.0;
770 cs->position[1] = 24.0;
771 cs->position[2] = 2.0;
772 cs->position[3] = 1.0;
775 cs->position2[0] = 5.0;
776 cs->position2[1] = 5.0;
777 cs->position2[2] = 5.0;
778 cs->position2[3] = 1.0;
783 cs->ground[3] = -0.00001;
788 if((cs->glx_context = init_GL(mi)))
789 reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi));
794 glDepthFunc(GL_LEQUAL);
796 glEnable(GL_CULL_FACE);
799 make_piece_texture(cs);
800 make_board_texture(cs);
802 gen_model_lists( classic, cs->poly_counts);
806 glColorMaterial(GL_FRONT, GL_DIFFUSE);
807 glShadeModel(smooth ? GL_SMOOTH : GL_FLAT);
808 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
809 glEnable(GL_DEPTH_TEST);
812 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
815 /** does dirty work drawing scene, moving pieces */
816 ENTRYPOINT void draw_chess(ModeInfo *mi)
818 Chesscreen *cs = &qs[MI_SCREEN(mi)];
819 Window w = MI_WINDOW(mi);
820 Display *disp = MI_DISPLAY(mi);
825 glXMakeCurrent(disp, w, *(cs->glx_context));
827 /** code for moving a piece */
828 if(cs->moving && ++cs->steps == 100) {
829 cs->moving = cs->count = cs->steps = cs->take = 0;
830 cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = cs->mpiece;
833 if(cs->mc == cs->game.movecount) {
839 if(++cs->count == 100) {
841 cs->mpiece = cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]];
842 cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]] = NONE;
844 if((cs->tpiece = cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]])) {
845 cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = NONE;
849 cs->from[0] = cs->game.moves[cs->mc][0];
850 cs->from[1] = cs->game.moves[cs->mc][1];
851 cs->to[0] = cs->game.moves[cs->mc][2];
852 cs->to[1] = cs->game.moves[cs->mc][3];
854 cs->dz = (cs->to[0] - cs->from[0]) / 100;
855 cs->dx = (cs->to[1] - cs->from[1]) / 100;
859 else if(cs->done == 1) {
860 int newgame = cs->oldgame;
861 while(newgame == cs->oldgame)
862 newgame = random()%GAMES;
865 cs->mod = 0.6 + (random()%20)/10.0;
868 cs->oldgame = newgame;
869 cs->game = games[cs->oldgame];
882 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION,
883 cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count);
884 glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION,
885 cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count);
886 glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.14);
887 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.14);
892 if(mi->fps_p) do_fps(mi);
894 glXSwapBuffers(disp, w);
898 ENTRYPOINT void release_chess(ModeInfo *mi)
907 XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess)