X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fendgame.c;h=e69a21c0ec3bbcfad70570ee2ebb1c9e55f55a0f;hp=cb64ededcc8c293dbc6e3c1887beaadfe134fd96;hb=4361b69d3178d7fc98d0388f9a223af6c2651aba;hpb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439 diff --git a/hacks/glx/endgame.c b/hacks/glx/endgame.c index cb64eded..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 @@ -21,6 +21,7 @@ "*wireframe: False \n" \ # define refresh_chess 0 +# define release_chess 0 # include "xlockmore.h" #else @@ -39,6 +40,13 @@ #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" }, @@ -55,18 +63,18 @@ static XrmOptionDescRec opts[] = { 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}, - {&classic, "classic", "Classic", "False", 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}, }; 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}; @@ -122,7 +130,7 @@ 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}, }; @@ -197,33 +205,16 @@ ENTRYPOINT Bool chess_handle_event (ModeInfo *mi, XEvent *event) { Chesscreen *cs = &qs[MI_SCREEN(mi)]; - if(event->xany.type == ButtonPress && event->xbutton.button == Button1) { - cs->button_down_p = True; - gltrackball_start (cs->trackball, - event->xbutton.x, event->xbutton.y, - MI_WIDTH (mi), MI_HEIGHT (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 == ButtonRelease - && event->xbutton.button == Button1) { - cs->button_down_p = False; - 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 (cs->trackball, event->xbutton.button, 5, - !event->xbutton.state); + cs->done = 1; return True; } - else if(event->xany.type == MotionNotify && cs->button_down_p) { - gltrackball_track (cs->trackball, - event->xmotion.x, event->xmotion.y, - MI_WIDTH (mi), MI_HEIGHT (mi)); - return True; - } - + return False; } @@ -300,6 +291,8 @@ static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow) { int piece = cs->mpiece % PIECES; + if (piece == NONE) return; + glPushMatrix(); if(shadow) glColor4fv(MaterialShadow); @@ -322,33 +315,42 @@ static void drawMovingPiece(ModeInfo *mi, Chesscreen *cs, int shadow) cs->mpiece = cs->mpiece == PAWN ? QUEEN : BQUEEN; } else if(cs->mpiece % PIECES == KNIGHT) { - GLfloat shine[1]; - GLfloat spec[4]; - GLfloat mult; - glTranslatef(cs->steps < 50 ? cs->from[1] : cs->to[1], 0.0, - cs->steps < 50 ? cs->from[0] : cs->to[0]); - - mult = cs->steps < 10 - ? (1.0 - cs->steps / 10.0) : 100 - cs->steps < 10 - ? (1.0 - (100 - cs->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); + /* 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; + } + } + } - 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(49-cs->steps)/49.0); + if (!blocked_p) + goto SLIDE; - glScalef(fabs(49-cs->steps)/49.0, fabs(49-cs->steps)/49.0, fabs(49-cs->steps)/49.0); - } - else + /* 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); + } + if(!cs->wire) glEnable(GL_BLEND); @@ -373,7 +375,7 @@ static void drawTakePiece(ModeInfo *mi, Chesscreen *cs, int shadow) glColor4f(shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][0], shadow ? MaterialShadow[1] : cs->colors[cs->tpiece/7][1], - shadow ? MaterialShadow[0] : cs->colors[cs->tpiece/7][2], + shadow ? MaterialShadow[2] : cs->colors[cs->tpiece/7][2], (100-1.6*cs->steps)/100.0); glTranslatef(cs->to[1], 0.0, cs->to[0]); @@ -423,15 +425,87 @@ static void drawBoard(ModeInfo *mi, Chesscreen *cs) mi->polygon_count++; } - - /* 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); */ 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); + } } static void draw_pieces(ModeInfo *mi, Chesscreen *cs, int wire) @@ -459,10 +533,75 @@ static void draw_shadow_pieces(ModeInfo *mi, Chesscreen *cs, int wire) 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); + + + 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}; @@ -558,17 +697,25 @@ static void display(ModeInfo *mi, Chesscreen *cs) 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 (cs->trackball); - glRotatef(cs->theta*100, 0.0, 1.0, 0.0); + + if (rotate) + glRotatef(cs->theta*100, 0.0, 1.0, 0.0); glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE); - 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; +/* 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; */ + + /* 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; 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); @@ -653,14 +800,12 @@ ENTRYPOINT void init_chess(ModeInfo *mi) Chesscreen *cs; int screen = MI_SCREEN(mi); - if(!qs && - !(qs = (Chesscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Chesscreen)))) - return; + MI_INIT(mi, qs, NULL); cs = &qs[screen]; cs->window = MI_WINDOW(mi); cs->wire = MI_IS_WIREFRAME(mi); - cs->trackball = gltrackball_init (); + cs->trackball = gltrackball_init (False); cs->oldwhite = -1; @@ -676,11 +821,17 @@ ENTRYPOINT void init_chess(ModeInfo *mi) 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] = 5.0; - cs->position[2] = 5.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; @@ -699,8 +850,6 @@ ENTRYPOINT void init_chess(ModeInfo *mi) else MI_CLEARWINDOW(mi); - glClearColor(0.0, 0.0, 0.0, 0.0); - if (!cs->wire) { glDepthFunc(GL_LEQUAL); glClearStencil(0); @@ -710,7 +859,11 @@ ENTRYPOINT void init_chess(ModeInfo *mi) make_piece_texture(cs); make_board_texture(cs); } - gen_model_lists( classic, cs->poly_counts); + chessmodels_gen_lists( classic, cs->poly_counts); + +# ifdef HAVE_JWZGLES /* #### glPolygonMode other than GL_FILL unimplemented */ + cs->wire = 0; +# endif if(!cs->wire) { setup_lights(cs); @@ -805,16 +958,6 @@ ENTRYPOINT void draw_chess(ModeInfo *mi) glXSwapBuffers(disp, w); } -/** bust it */ -ENTRYPOINT void release_chess(ModeInfo *mi) -{ - if(qs) - free((void *) qs); - qs = 0; - - FreeAllGL(mi); -} - XSCREENSAVER_MODULE_2 ("Endgame", endgame, chess) #endif