X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fendgame.c;h=e69a21c0ec3bbcfad70570ee2ebb1c9e55f55a0f;hp=30f4e7dfff067a501050382fc7b2cddd99e685b8;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hpb=447db08c956099b3b183886729108bf5b364c4b8 diff --git a/hacks/glx/endgame.c b/hacks/glx/endgame.c index 30f4e7df..e69a21c0 100644 --- a/hacks/glx/endgame.c +++ b/hacks/glx/endgame.c @@ -4,7 +4,7 @@ * * version 1.0 - June 6, 2002 * - * Copyright (C) 2002 Blair Tennessy (tennessb@unbc.ca) + * Copyright (C) 2002-2008 Blair Tennessy (tennessb@unbc.ca) * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -15,21 +15,13 @@ * implied warranty. */ -#include - #ifdef STANDALONE -# define PROGCLASS "Endgame" -# define HACK_INIT init_chess -# define HACK_DRAW draw_chess -# define HACK_RESHAPE reshape_chess -# define HACK_HANDLE_EVENT chess_handle_event -# define EVENT_MASK PointerMotionMask -# define chess_opts xlockmore_opts - #define DEFAULTS "*delay: 20000 \n" \ "*showFPS: False \n" \ "*wireframe: False \n" \ +# define refresh_chess 0 +# define release_chess 0 # include "xlockmore.h" #else @@ -38,13 +30,23 @@ #ifdef USE_GL -#include +#define BOARDSIZE 8 +#define WHITES 5 + #include "gltrackball.h" #include "chessmodels.h" +#include "chessgames.h" #undef countof #define countof(x) (sizeof((x))/sizeof((*x))) +#define DEF_ROTATE "True" +#define DEF_REFLECTIONS "True" +#define DEF_SHADOWS "True" +#define DEF_SMOOTH "True" +#define DEF_CLASSIC "False" + + static XrmOptionDescRec opts[] = { {"+rotate", ".chess.rotate", XrmoptionNoArg, "false" }, {"-rotate", ".chess.rotate", XrmoptionNoArg, "true" }, @@ -54,110 +56,114 @@ static XrmOptionDescRec opts[] = { {"-shadows", ".chess.shadows", XrmoptionNoArg, "true" }, {"+smooth", ".chess.smooth", XrmoptionNoArg, "false" }, {"-smooth", ".chess.smooth", XrmoptionNoArg, "true" }, + {"+classic", ".chess.classic", XrmoptionNoArg, "false" }, + {"-classic", ".chess.classic", XrmoptionNoArg, "true" }, }; -int rotate, reflections, smooth, shadows; +static int rotate, reflections, smooth, shadows, classic; static argtype vars[] = { - {&rotate, "rotate", "Rotate", "True", t_Bool}, - {&reflections, "reflections", "Reflections", "True", t_Bool}, - {&shadows, "shadows", "Shadows", "True", t_Bool}, - {&smooth, "smooth", "Smooth", "True", t_Bool}, + {&rotate, "rotate", "Rotate", DEF_ROTATE, t_Bool}, + {&reflections, "reflections", "Reflections", DEF_REFLECTIONS, t_Bool}, + {&shadows, "shadows", "Shadows", DEF_SHADOWS, t_Bool}, + {&smooth, "smooth", "Smooth", DEF_SMOOTH, t_Bool}, + {&classic, "classic", "Classic", DEF_CLASSIC, t_Bool}, }; -ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, NULL}; +ENTRYPOINT ModeSpecOpt chess_opts = {countof(opts), opts, countof(vars), vars, NULL}; #ifdef USE_MODULES ModStruct chess_description = -{"chess", "init_chess", "draw_chess", "release_chess", +{"chess", "init_chess", "draw_chess", NULL, "draw_chess", "init_chess", NULL, &chess_opts, 1000, 1, 2, 1, 4, 1.0, "", "Chess", 0, NULL}; #endif +#define checkImageWidth 16 +#define checkImageHeight 16 + typedef struct { GLXContext *glx_context; Window window; trackball_state *trackball; Bool button_down_p; -} Chesscreen; -static Chesscreen *qs = NULL; + ChessGame game; + int oldwhite; -#include -#include -#include -#include + /** definition of white/black (orange/gray) colors */ + GLfloat colors[2][3]; -#ifndef M_PI -#define M_PI 3.14159265 -#endif + GLubyte checkImage[checkImageWidth][checkImageHeight][3]; + GLuint piecetexture, boardtexture; -#define BOARDSIZE 8 + int mpiece, tpiece, steps, done; + double from[2], to[2]; + double dx, dz; + int moving, take, mc, count, wire; + double theta; -static float MaterialShadow[] = {0.0, 0.0, 0.0, 0.3}; + GLfloat position[4]; + GLfloat position2[4]; + GLfloat mod; + GLfloat ground[4]; -/** definition of white/black (orange/gray) colors */ -GLfloat colors[2][3] = - { - {1.0, 0.5, 0.0}, - {0.6, 0.6, 0.6}, - }; + int oldgame; + + int poly_counts[PIECES]; /* polygon count of each type of piece */ + + +} Chesscreen; + +static Chesscreen *qs = NULL; + +static const GLfloat MaterialShadow[] = {0.0, 0.0, 0.0, 0.3}; -#define WHITES 5 /* i prefer silvertip */ -GLfloat whites[WHITES][3] = +static const GLfloat whites[WHITES][3] = { {1.0, 0.55, 0.1}, {0.8, 0.52, 0.8}, {0.43, 0.54, 0.76}, - {0.8, 0.8, 0.8}, + {0.2, 0.2, 0.2}, {0.35, 0.60, 0.35}, }; -#include "chessgames.h" - -ChessGame game; -int oldwhite = -1; - -void build_colors(void) { +static void build_colors(Chesscreen *cs) +{ /* find new white */ - int newwhite = oldwhite; - while(newwhite == oldwhite) + int newwhite = cs->oldwhite; + while(newwhite == cs->oldwhite) newwhite = random()%WHITES; - oldwhite = newwhite; + cs->oldwhite = newwhite; - colors[0][0] = whites[oldwhite][0]; - colors[0][1] = whites[oldwhite][1]; - colors[0][2] = whites[oldwhite][2]; + cs->colors[0][0] = whites[cs->oldwhite][0]; + cs->colors[0][1] = whites[cs->oldwhite][1]; + cs->colors[0][2] = whites[cs->oldwhite][2]; } -/* road texture */ -#define checkImageWidth 16 -#define checkImageHeight 16 -GLubyte checkImage[checkImageWidth][checkImageHeight][3]; -GLuint piecetexture, boardtexture; - /* build piece texture */ -void make_piece_texture(void) { +static void make_piece_texture(Chesscreen *cs) +{ int i, j, c; for (i = 0; i < checkImageWidth; i++) { for (j = 0; j < checkImageHeight; j++) { c = ((j%2) == 0 || i%2 == 0) ? 240 : 180+random()%16; - checkImage[i][j][0] = (GLubyte) c; - checkImage[i][j][1] = (GLubyte) c; - checkImage[i][j][2] = (GLubyte) c; + cs->checkImage[i][j][0] = (GLubyte) c; + cs->checkImage[i][j][1] = (GLubyte) c; + cs->checkImage[i][j][2] = (GLubyte) c; } } - glGenTextures(1, &piecetexture); - glBindTexture(GL_TEXTURE_2D, piecetexture); + glGenTextures(1, &cs->piecetexture); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); @@ -165,24 +171,25 @@ void make_piece_texture(void) { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, - &checkImage[0][0]); + &cs->checkImage[0][0]); } /* build board texture (uniform noise in [180,180+50]) */ -void make_board_texture(void) { +static void make_board_texture(Chesscreen *cs) +{ int i, j, c; for (i = 0; i < checkImageWidth; i++) { for (j = 0; j < checkImageHeight; j++) { c = 180 + random()%51; - checkImage[i][j][0] = (GLubyte) c; - checkImage[i][j][1] = (GLubyte) c; - checkImage[i][j][2] = (GLubyte) c; + cs->checkImage[i][j][0] = (GLubyte) c; + cs->checkImage[i][j][1] = (GLubyte) c; + cs->checkImage[i][j][2] = (GLubyte) c; } } - glGenTextures(1, &boardtexture); - glBindTexture(GL_TEXTURE_2D, boardtexture); + glGenTextures(1, &cs->boardtexture); + glBindTexture(GL_TEXTURE_2D, cs->boardtexture); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); @@ -190,61 +197,37 @@ void make_board_texture(void) { glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexImage2D(GL_TEXTURE_2D, 0, 3, checkImageWidth, checkImageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, - &checkImage[0][0]); + &cs->checkImage[0][0]); } -/* yay its c */ -int mpiece = 0, tpiece, steps = 0, done = 1; -double from[2], to[2]; -double dx, dz; -int moving = 0, take = 0, mc = 0, count = 99, wire = 0; -double theta = 0.0; - /** handle X event (trackball) */ -Bool chess_handle_event (ModeInfo *mi, XEvent *event) { - Chesscreen *c = &qs[MI_SCREEN(mi)]; - - if(event->xany.type == ButtonPress && event->xbutton.button == Button1) { - c->button_down_p = True; - gltrackball_start (c->trackball, - event->xbutton.x, event->xbutton.y, - MI_WIDTH (mi), MI_HEIGHT (mi)); - return True; - } - else if(event->xany.type == ButtonRelease - && event->xbutton.button == Button1) { - c->button_down_p = False; +ENTRYPOINT Bool chess_handle_event (ModeInfo *mi, XEvent *event) +{ + Chesscreen *cs = &qs[MI_SCREEN(mi)]; + + if (gltrackball_event_handler (event, cs->trackball, + MI_WIDTH (mi), MI_HEIGHT (mi), + &cs->button_down_p)) return True; - } - else if (event->xany.type == ButtonPress && - (event->xbutton.button == Button4 || - event->xbutton.button == Button5)) + else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event)) { - gltrackball_mousewheel (c->trackball, event->xbutton.button, 5, - !event->xbutton.state); + cs->done = 1; return True; } - else if(event->xany.type == MotionNotify && c->button_down_p) { - gltrackball_track (c->trackball, - event->xmotion.x, event->xmotion.y, - MI_WIDTH (mi), MI_HEIGHT (mi)); - return True; - } - + return False; } -GLfloat position[] = { 0.0, 5.0, 5.0, 1.0 }; -GLfloat position2[] = { 5.0, 5.0, 5.0, 1.0 }; -GLfloat diffuse2[] = {1.0, 1.0, 1.0, 1.0}; -GLfloat ambient2[] = {0.7, 0.7, 0.7, 1.0}; -GLfloat shininess[] = {60.0}; -GLfloat specular[] = {0.4, 0.4, 0.4, 1.0}; +static const GLfloat diffuse2[] = {1.0, 1.0, 1.0, 1.0}; +/*static const GLfloat ambient2[] = {0.7, 0.7, 0.7, 1.0};*/ +static const GLfloat shininess[] = {60.0}; +static const GLfloat specular[] = {0.4, 0.4, 0.4, 1.0}; /* configure lighting */ -void setup_lights(void) { +static void setup_lights(Chesscreen *cs) +{ glEnable(GL_LIGHTING); - glLightfv(GL_LIGHT0, GL_POSITION, position); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse2); glEnable(GL_LIGHT0); @@ -259,15 +242,17 @@ void setup_lights(void) { } /* draw pieces */ -void drawPieces(void) { +static void drawPieces(ModeInfo *mi, Chesscreen *cs) +{ int i, j; for(i = 0; i < BOARDSIZE; ++i) { for(j = 0; j < BOARDSIZE; ++j) { - if(game.board[i][j]) { - int c = game.board[i][j]/PIECES; - glColor3fv(colors[c]); - glCallList(game.board[i][j]%PIECES); + if(cs->game.board[i][j]) { + int c = cs->game.board[i][j]/PIECES; + glColor3fv(cs->colors[c]); + glCallList(cs->game.board[i][j]%PIECES); + mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES]; } glTranslatef(1.0, 0.0, 0.0); @@ -280,14 +265,16 @@ void drawPieces(void) { } /* draw pieces */ -void drawPiecesShadow(void) { +static void drawPiecesShadow(ModeInfo *mi, Chesscreen *cs) +{ int i, j; for(i = 0; i < BOARDSIZE; ++i) { for(j = 0; j < BOARDSIZE; ++j) { - if(game.board[i][j]) { + if(cs->game.board[i][j]) { glColor4f(0.0, 0.0, 0.0, 0.4); - glCallList(game.board[i][j]%PIECES); + glCallList(cs->game.board[i][j]%PIECES); + mi->polygon_count += cs->poly_counts[cs->game.board[i][j]%PIECES]; } glTranslatef(1.0, 0.0, 0.0); @@ -300,113 +287,127 @@ void drawPiecesShadow(void) { } /* draw a moving piece */ -void drawMovingPiece(int shadow) { - int piece = mpiece % PIECES; +static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow) +{ + int piece = cs->mpiece % PIECES; + + if (piece == NONE) return; glPushMatrix(); if(shadow) glColor4fv(MaterialShadow); - else glColor3fv(colors[mpiece/PIECES]); + else glColor3fv(cs->colors[cs->mpiece/PIECES]); /** assume a queening. should be more general */ - if((mpiece == PAWN && fabs(to[0]) < 0.01) || - (mpiece == BPAWN && fabs(to[0]-7.0) < 0.01)) { - glTranslatef(from[1]+steps*dx, 0.0, from[0]+steps*dz); + if((cs->mpiece == PAWN && fabs(cs->to[0]) < 0.01) || + (cs->mpiece == BPAWN && fabs(cs->to[0]-7.0) < 0.01)) { + glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz); - glColor4f(shadow ? MaterialShadow[0] : colors[mpiece/7][0], - shadow ? MaterialShadow[1] : colors[mpiece/7][1], - shadow ? MaterialShadow[2] : colors[mpiece/7][2], - (fabs(50.0-steps))/50.0); + glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->mpiece/7][0], + shadow ? MaterialShadow[1] : cs->colors[cs->mpiece/7][1], + shadow ? MaterialShadow[2] : cs->colors[cs->mpiece/7][2], + (fabs(50.0-cs->steps))/50.0); - piece = steps < 50 ? PAWN : QUEEN; + piece = cs->steps < 50 ? PAWN : QUEEN; /* what a kludge */ - if(steps == 99) - mpiece = mpiece == PAWN ? QUEEN : BQUEEN; + if(cs->steps == 99) + cs->mpiece = cs->mpiece == PAWN ? QUEEN : BQUEEN; } - else if(mpiece % PIECES == KNIGHT) { - GLfloat shine[1]; - GLfloat spec[4]; - GLfloat mult; - glTranslatef(steps < 50 ? from[1] : to[1], 0.0, - steps < 50 ? from[0] : to[0]); - - mult = steps < 10 - ? (1.0 - steps / 10.0) : 100 - steps < 10 - ? (1.0 - (100 - steps) / 10.0) : 0.0; - - shine[0] = mult*shininess[0]; - spec[0] = mult*specular[0]; - spec[1] = mult*specular[1]; - spec[2] = mult*specular[2]; - spec[3] = 1.0; - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shine); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec); - - glColor4f(shadow ? MaterialShadow[0] : colors[mpiece/7][0], - shadow ? MaterialShadow[1] : colors[mpiece/7][1], - shadow ? MaterialShadow[2] : colors[mpiece/7][2], - fabs(49-steps)/49.0); - - glScalef(fabs(49-steps)/49.0, fabs(49-steps)/49.0, fabs(49-steps)/49.0); + else if(cs->mpiece % PIECES == KNIGHT) { + /* If there is nothing in the path of a knight, move it by sliding, + just like the other pieces. But if there are any pieces on the + middle two squares in its path, the knight would intersect them, + so in that case, move it in an airborne arc. */ + GLfloat y; + int i, j; + Bool blocked_p = False; + int fromx = MIN(cs->from[1], cs->to[1]); + int fromy = MIN(cs->from[0], cs->to[0]); + int tox = MAX(cs->from[1], cs->to[1]); + int toy = MAX(cs->from[0], cs->to[0]); + if (fromx == tox-2) fromx = tox = fromx+1; + if (fromy == toy-2) fromy = toy = fromy+1; + for (i = fromy; i <= toy; i++) { + for (j = fromx; j <= tox; j++) { + if (cs->game.board[i][j]) { + blocked_p = True; + break; + } + } + } + + if (!blocked_p) + goto SLIDE; + + /* Move by hopping. */ + y = 1.5 * sin (M_PI * cs->steps / 100.0); + glTranslatef(cs->from[1]+cs->steps*cs->dx, y, + cs->from[0]+cs->steps*cs->dz); + + } else { + SLIDE: + /* Move by sliding. */ + glTranslatef(cs->from[1]+cs->steps*cs->dx, 0.0, cs->from[0]+cs->steps*cs->dz); } - else - glTranslatef(from[1]+steps*dx, 0.0, from[0]+steps*dz); - if(!wire) + + if(!cs->wire) glEnable(GL_BLEND); glCallList(piece); + mi->polygon_count += cs->poly_counts[cs->mpiece % PIECES]; glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shininess); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); glPopMatrix(); - if(!wire) + if(!cs->wire) glDisable(GL_BLEND); } /** code to squish a taken piece */ -void drawTakePiece(int shadow) { - if(!wire) +static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow) +{ + if(!cs->wire) glEnable(GL_BLEND); - glColor4f(shadow ? MaterialShadow[0] : colors[tpiece/7][0], - shadow ? MaterialShadow[1] : colors[tpiece/7][1], - shadow ? MaterialShadow[0] : colors[tpiece/7][2], - (100-1.6*steps)/100.0); + glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][0], + shadow ? MaterialShadow[1] : cs->colors[cs->tpiece/7][1], + shadow ? MaterialShadow[2] : cs->colors[cs->tpiece/7][2], + (100-1.6*cs->steps)/100.0); - glTranslatef(to[1], 0.0, to[0]); + glTranslatef(cs->to[1], 0.0, cs->to[0]); - if(mpiece % PIECES == KNIGHT) - glScalef(1.0+steps/100.0, 1.0, 1.0+steps/100.0); + if(cs->mpiece % PIECES == KNIGHT) + glScalef(1.0+cs->steps/100.0, 1.0, 1.0+cs->steps/100.0); else - glScalef(1.0, 1 - steps/50.0 > 0.01 ? 1 - steps/50.0 : 0.01, 1.0); - glCallList(tpiece % 7); + glScalef(1.0, 1 - cs->steps/50.0 > 0.01 ? 1 - cs->steps/50.0 : 0.01, 1.0); + glCallList(cs->tpiece % 7); + mi->polygon_count += cs->poly_counts[cs->tpiece % PIECES]; - if(!wire) + if(!cs->wire) glDisable(GL_BLEND); } -double mod = 1.4; - /** draw board */ -void drawBoard(void) { +static void drawBoard(ModeInfo *mi, Chesscreen *cs) +{ int i, j; glBegin(GL_QUADS); for(i = 0; i < BOARDSIZE; ++i) for(j = 0; j < BOARDSIZE; ++j) { - double ma1 = (i+j)%2 == 0 ? mod*i : 0.0; - double mb1 = (i+j)%2 == 0 ? mod*j : 0.0; - double ma2 = (i+j)%2 == 0 ? mod*(i+1.0) : 0.01; - double mb2 = (i+j)%2 == 0 ? mod*(j+1.0) : 0.01; + double ma1 = (i+j)%2 == 0 ? cs->mod*i : 0.0; + double mb1 = (i+j)%2 == 0 ? cs->mod*j : 0.0; + double ma2 = (i+j)%2 == 0 ? cs->mod*(i+1.0) : 0.01; + double mb2 = (i+j)%2 == 0 ? cs->mod*(j+1.0) : 0.01; /*glColor3fv(colors[(i+j)%2]);*/ - glColor4f(colors[(i+j)%2][0], colors[(i+j)%2][1], - colors[(i+j)%2][2], 0.65); + glColor4f(cs->colors[(i+j)%2][0], cs->colors[(i+j)%2][1], + cs->colors[(i+j)%2][2], 0.65); glNormal3f(0.0, 1.0, 0.0); /* glTexCoord2f(mod*i, mod*(j+1.0)); */ @@ -421,51 +422,196 @@ void drawBoard(void) { glTexCoord2f(ma1, mb1); /* glTexCoord2f(mod*i, mod*j); */ glVertex3f(i, 0.0, j); - } - /* chop underneath board */ -/* glColor3f(0, 0, 0); */ -/* glNormal3f(0, -1, 0); */ -/* glVertex3f(0, 0, BOARDSIZE); */ -/* glVertex3f(0, 0, 0); */ -/* glVertex3f(BOARDSIZE, 0, 0); */ -/* glVertex3f(BOARDSIZE, 0, BOARDSIZE); */ + mi->polygon_count++; + } glEnd(); + + { + GLfloat off = 0.01; + GLfloat w = BOARDSIZE; + GLfloat h = 0.1; + + /* Give the board a slight lip. */ + /* #### oops, normals are wrong here, but you can't tell */ + + glColor3f(0.3, 0.3, 0.3); + glBegin (GL_QUADS); + glVertex3f (0, 0, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, -h, w); + glVertex3f (0, 0, w); + + glVertex3f (0, 0, w); + glVertex3f (0, -h, w); + glVertex3f (w, -h, w); + glVertex3f (w, 0, w); + + glVertex3f (w, 0, w); + glVertex3f (w, -h, w); + glVertex3f (w, -h, 0); + glVertex3f (w, 0, 0); + + glVertex3f (w, 0, 0); + glVertex3f (w, -h, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, 0, 0); + + glVertex3f (0, -h, 0); + glVertex3f (w, -h, 0); + glVertex3f (w, -h, w); + glVertex3f (0, -h, w); + glEnd(); + mi->polygon_count += 4; + + /* Fill in the underside of the board with an invisible black box + to hide the reflections that are not on tiles. Probably there's + a way to do this with stencils instead. + */ + w -= off*2; + h = 5; + + glPushMatrix(); + glTranslatef (off, 0, off); + glDisable(GL_LIGHTING); + glColor3f(0,0,0); + glBegin (GL_QUADS); + glVertex3f (0, 0, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, -h, w); + glVertex3f (0, 0, w); + + glVertex3f (0, 0, w); + glVertex3f (0, -h, w); + glVertex3f (w, -h, w); + glVertex3f (w, 0, w); + + glVertex3f (w, 0, w); + glVertex3f (w, -h, w); + glVertex3f (w, -h, 0); + glVertex3f (w, 0, 0); + + glVertex3f (w, 0, 0); + glVertex3f (w, -h, 0); + glVertex3f (0, -h, 0); + glVertex3f (0, 0, 0); + + glVertex3f (0, -h, 0); + glVertex3f (w, -h, 0); + glVertex3f (w, -h, w); + glVertex3f (0, -h, w); + glEnd(); + mi->polygon_count += 4; + glPopMatrix(); + if (!cs->wire) + glEnable(GL_LIGHTING); + } } -void draw_pieces(void) { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, piecetexture); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire) +{ + if (!cs->wire) { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glColor4f(0.5, 0.5, 0.5, 1.0); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + glColor4f(0.5, 0.5, 0.5, 1.0); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); + } - drawPieces(); - if(moving) drawMovingPiece(0); - if(take) drawTakePiece(0); + drawPieces(mi, cs); + if(cs->moving) drawMovingPiece(mi, cs, 0); + if(cs->take) drawTakePiece(mi, cs, 0); glDisable(GL_TEXTURE_2D); } -void draw_shadow_pieces(void) { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, piecetexture); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire) +{ + if (!cs->wire) { + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, cs->piecetexture); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + /* use the stencil */ + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + + glClear(GL_STENCIL_BUFFER_BIT); + glColorMask(0,0,0,0); + glEnable(GL_STENCIL_TEST); + + glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFFL); + glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); - drawPiecesShadow(); - if(moving) drawMovingPiece(shadows); - if(take) drawTakePiece(shadows); + + glPushMatrix(); + glTranslatef(0.0, 0.001, 0.0); + + /* draw the pieces */ + drawPiecesShadow(mi, cs); + if(cs->moving) drawMovingPiece(mi, cs, shadows); + if(cs->take) drawTakePiece(mi, cs, shadows); + + glPopMatrix(); + + + /* turn on drawing into colour buffer */ + glColorMask(1,1,1,1); + + /* programming with effect */ + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); glDisable(GL_TEXTURE_2D); + + /* now draw the union of the shadows */ + + /* + + want to keep alpha values (alpha is involved in transition + effects of the active pieces). + + */ + glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFFL); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + + glEnable(GL_BLEND); + + glColor4fv(MaterialShadow); + + /* draw the board generously to fill the shadows */ + glBegin(GL_QUADS); + + glVertex3f(-1.0, 0.0, -1.0); + glVertex3f(-1.0, 0.0, BOARDSIZE + 1.0); + glVertex3f(1.0 + BOARDSIZE, 0.0, BOARDSIZE + 1.0); + glVertex3f(1.0 + BOARDSIZE, 0.0, -1.0); + + glEnd(); + + glDisable(GL_STENCIL_TEST); + + /* "pop" attributes */ + glEnable(GL_TEXTURE_2D); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_LIGHTING); + glEnable(GL_CULL_FACE); + + + } enum {X, Y, Z, W}; enum {A, B, C, D}; /* create a matrix that will project the desired shadow */ -void shadowmatrix(GLfloat shadowMat[4][4], +static void shadowmatrix(GLfloat shadowMat[4][4], GLfloat groundplane[4], - GLfloat lightpos[4]) { + GLfloat lightpos[4]) +{ GLfloat dot; /* find dot product between light position vector and ground plane normal */ @@ -495,10 +641,9 @@ void shadowmatrix(GLfloat shadowMat[4][4], shadowMat[3][3] = dot - lightpos[W] * groundplane[W]; } -GLfloat ground[4] = {0.0, 1.0, 0.0, -0.00001}; - /** reflectionboard */ -void draw_reflections(void) { +static void draw_reflections(ModeInfo *mi, Chesscreen *cs) +{ int i, j; glEnable(GL_STENCIL_TEST); @@ -517,6 +662,7 @@ void draw_reflections(void) { glVertex3f(i + 1.0, 0.0, j + 1.0); glVertex3f(i + 1.0, 0.0, j); glVertex3f(i, 0.0, j); + mi->polygon_count++; } } glEnd(); @@ -530,12 +676,12 @@ void draw_reflections(void) { glScalef(1.0, -1.0, 1.0); glTranslatef(0.5, 0.0, 0.5); - glLightfv(GL_LIGHT0, GL_POSITION, position); - draw_pieces(); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + draw_pieces(mi, cs, cs->wire); glPopMatrix(); glDisable(GL_STENCIL_TEST); - glLightfv(GL_LIGHT0, GL_POSITION, position); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); @@ -543,50 +689,63 @@ void draw_reflections(void) { } /** draws the scene */ -void display(Chesscreen *c) { +static void display(ModeInfo *mi, Chesscreen *cs) +{ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + mi->polygon_count = 0; + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + glRotatef(current_device_rotation(), 0, 0, 1); - /** setup perspectif */ + /** setup perspectiv */ glTranslatef(0.0, 0.0, -1.5*BOARDSIZE); glRotatef(30.0, 1.0, 0.0, 0.0); - gltrackball_rotate (c->trackball); - glRotatef(theta*100, 0.0, 1.0, 0.0); + gltrackball_rotate (cs->trackball); + + if (rotate) + glRotatef(cs->theta*100, 0.0, 1.0, 0.0); glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE); - position[0] = 4.0 + 1.0*-sin(theta*100*M_PI/180.0); - position[2] = 4.0 + 1.0*cos(theta*100*M_PI/180.0); - position[1] = 5.0; +/* cs->position[0] = 4.0 + 1.0*-sin(cs->theta*100*M_PI/180.0); */ +/* cs->position[2] = 4.0 + 1.0* cos(cs->theta*100*M_PI/180.0); */ +/* cs->position[1] = 5.0; */ - position2[0] = 4.0 + 8.0*-sin(theta*100*M_PI/180.0); - position2[2] = 4.0 + 8.0*cos(theta*100*M_PI/180.0); + /* this is the lone light that the shadow matrix is generated from */ + cs->position[0] = 1.0; + cs->position[2] = 1.0; + cs->position[1] = 16.0; - glEnable(GL_LIGHTING); - glLightfv(GL_LIGHT0, GL_POSITION, position); - glLightfv(GL_LIGHT1, GL_POSITION, position2); - glEnable(GL_LIGHT0); + cs->position2[0] = 4.0 + 8.0*-sin(cs->theta*100*M_PI/180.0); + cs->position2[2] = 4.0 + 8.0* cos(cs->theta*100*M_PI/180.0); + + if (!cs->wire) { + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, cs->position); + glLightfv(GL_LIGHT1, GL_POSITION, cs->position2); + glEnable(GL_LIGHT0); + } /** draw board, pieces */ - if(!wire) { + if(!cs->wire) { glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); - if(reflections) { - draw_reflections(); + if(reflections && !cs->wire) { + draw_reflections(mi, cs); glEnable(GL_BLEND); } glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, boardtexture); - drawBoard(); + glBindTexture(GL_TEXTURE_2D, cs->boardtexture); + drawBoard(mi, cs); glDisable(GL_TEXTURE_2D); if(shadows) { /* render shadows */ GLfloat m[4][4]; - shadowmatrix(m, ground, position); + shadowmatrix(m, cs->ground, cs->position); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialShadow); glEnable(GL_BLEND); @@ -598,7 +757,7 @@ void display(Chesscreen *c) { glTranslatef(0.0, 0.001, 0.0); glMultMatrixf(m[0]); glTranslatef(0.5, 0.01, 0.5); - draw_shadow_pieces(); + draw_shadow_pieces(mi, cs, cs->wire); glPopMatrix(); glEnable(GL_LIGHTING); @@ -610,22 +769,23 @@ void display(Chesscreen *c) { glDisable(GL_BLEND); } else - drawBoard(); + drawBoard(mi, cs); glTranslatef(0.5, 0.0, 0.5); - draw_pieces(); + draw_pieces(mi, cs, cs->wire); - if(!wire) { + if(!cs->wire) { glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); } - if (!c->button_down_p) - theta += .002; + if (!cs->button_down_p) + cs->theta += .002; } /** reshape handler */ -void reshape_chess(ModeInfo *mi, int width, int height) { +ENTRYPOINT void reshape_chess(ModeInfo *mi, int width, int height) +{ GLfloat h = (GLfloat) height / (GLfloat) width; glViewport(0,0, width, height); glMatrixMode(GL_PROJECTION); @@ -635,135 +795,169 @@ void reshape_chess(ModeInfo *mi, int width, int height) { } /** initialization handler */ -void init_chess(ModeInfo *mi) { - Chesscreen *c; +ENTRYPOINT void init_chess(ModeInfo *mi) +{ + Chesscreen *cs; int screen = MI_SCREEN(mi); - wire = MI_IS_WIREFRAME(mi); - if(!qs && - !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen)))) - return; + MI_INIT(mi, qs, NULL); - c = &qs[screen]; - c->window = MI_WINDOW(mi); - c->trackball = gltrackball_init (); + cs = &qs[screen]; + cs->window = MI_WINDOW(mi); + cs->wire = MI_IS_WIREFRAME(mi); + cs->trackball = gltrackball_init (False); - if((c->glx_context = init_GL(mi))) + cs->oldwhite = -1; + + cs->colors[0][0] = 1.0; + cs->colors[0][1] = 0.5; + cs->colors[0][2] = 0.0; + + cs->colors[1][0] = 0.6; + cs->colors[1][1] = 0.6; + cs->colors[1][2] = 0.6; + + cs->done = 1; + cs->count = 99; + cs->mod = 1.4; + +/* cs->position[0] = 0.0; */ +/* cs->position[1] = 5.0; */ +/* cs->position[2] = 5.0; */ +/* cs->position[3] = 1.0; */ + + cs->position[0] = 0.0; + cs->position[1] = 24.0; + cs->position[2] = 2.0; + cs->position[3] = 1.0; + + + cs->position2[0] = 5.0; + cs->position2[1] = 5.0; + cs->position2[2] = 5.0; + cs->position2[3] = 1.0; + + cs->ground[0] = 0.0; + cs->ground[1] = 1.0; + cs->ground[2] = 0.0; + cs->ground[3] = -0.00001; + + cs->oldgame = -1; + + + if((cs->glx_context = init_GL(mi))) reshape_chess(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); else MI_CLEARWINDOW(mi); - glClearColor(0.0, 0.0, 0.0, 0.0); + if (!cs->wire) { + glDepthFunc(GL_LEQUAL); + glClearStencil(0); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); - glDepthFunc(GL_LEQUAL); - glClearStencil(0); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); + make_piece_texture(cs); + make_board_texture(cs); + } + chessmodels_gen_lists( classic, cs->poly_counts); - make_piece_texture(); - make_board_texture(); - gen_model_lists(); +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + cs->wire = 0; +# endif - if(!wire) { - setup_lights(); + if(!cs->wire) { + setup_lights(cs); glColorMaterial(GL_FRONT, GL_DIFFUSE); glShadeModel(smooth ? GL_SMOOTH : GL_FLAT); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); } else - glPolygonMode(GL_FRONT, GL_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } -int oldgame = -1; - /** does dirty work drawing scene, moving pieces */ -void draw_chess(ModeInfo *mi) { - Chesscreen *c = &qs[MI_SCREEN(mi)]; +ENTRYPOINT void draw_chess(ModeInfo *mi) +{ + Chesscreen *cs = &qs[MI_SCREEN(mi)]; Window w = MI_WINDOW(mi); Display *disp = MI_DISPLAY(mi); - if(!c->glx_context) + if(!cs->glx_context) return; - glXMakeCurrent(disp, w, *(c->glx_context)); + glXMakeCurrent(disp, w, *(cs->glx_context)); /** code for moving a piece */ - if(moving && ++steps == 100) { - moving = count = steps = take = 0; - game.board[game.moves[mc][2]][game.moves[mc][3]] = mpiece; - ++mc; + if(cs->moving && ++cs->steps == 100) { + cs->moving = cs->count = cs->steps = cs->take = 0; + cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = cs->mpiece; + ++cs->mc; - if(mc == game.movecount) { - done = 1; - mc = 0; + if(cs->mc == cs->game.movecount) { + cs->done = 1; + cs->mc = 0; } } - if(++count == 100) { - if(!done) { - mpiece = game.board[game.moves[mc][0]][game.moves[mc][1]]; - game.board[game.moves[mc][0]][game.moves[mc][1]] = NONE; + if(++cs->count == 100) { + if(!cs->done) { + cs->mpiece = cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]]; + cs->game.board[cs->game.moves[cs->mc][0]][cs->game.moves[cs->mc][1]] = NONE; - if((tpiece = game.board[game.moves[mc][2]][game.moves[mc][3]])) { - game.board[game.moves[mc][2]][game.moves[mc][3]] = NONE; - take = 1; + if((cs->tpiece = cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]])) { + cs->game.board[cs->game.moves[cs->mc][2]][cs->game.moves[cs->mc][3]] = NONE; + cs->take = 1; } - from[0] = game.moves[mc][0]; - from[1] = game.moves[mc][1]; - to[0] = game.moves[mc][2]; - to[1] = game.moves[mc][3]; + cs->from[0] = cs->game.moves[cs->mc][0]; + cs->from[1] = cs->game.moves[cs->mc][1]; + cs->to[0] = cs->game.moves[cs->mc][2]; + cs->to[1] = cs->game.moves[cs->mc][3]; - dz = (to[0] - from[0]) / 100; - dx = (to[1] - from[1]) / 100; - steps = 0; - moving = 1; + cs->dz = (cs->to[0] - cs->from[0]) / 100; + cs->dx = (cs->to[1] - cs->from[1]) / 100; + cs->steps = 0; + cs->moving = 1; } - else if(done == 1) { - int newgame = oldgame; - while(newgame == oldgame) + else if(cs->done == 1) { + int newgame = cs->oldgame; + while(newgame == cs->oldgame) newgame = random()%GAMES; /* mod the mod */ - mod = 0.6 + (random()%20)/10.0; + cs->mod = 0.6 + (random()%20)/10.0; /* same old game */ - oldgame = newgame; - game = games[oldgame]; - build_colors(); - done = 2; - count = 0; + cs->oldgame = newgame; + cs->game = games[cs->oldgame]; + build_colors(cs); + cs->done = 2; + cs->count = 0; } else { - done = 0; - count = 0; + cs->done = 0; + cs->count = 0; } } /* set lighting */ - if(done) { + if(cs->done) { glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, - done == 1 ? 1.0+0.1*count : 100.0/count); + cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count); glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, - done == 1 ? 1.0+0.1*count : 100.0/count); + cs->done == 1 ? 1.0+0.1*cs->count : 100.0/cs->count); glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.14); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.14); } - display(c); + display(mi, cs); if(mi->fps_p) do_fps(mi); glFinish(); glXSwapBuffers(disp, w); } -/** bust it */ -void release_chess(ModeInfo *mi) { - if(qs) - free((void *) qs); - - FreeAllGL(MI); -} +XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess) #endif