X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fqueens.c;h=3c671aff04b5edf087d523e97e8a471aba9082df;hp=ba14cc7be888a03cbc4dde3f4d29edaf1b2170c7;hb=6b1c86cf395f59389e4ece4ea8f4bea2c332745b;hpb=c28aecf9fc41e3a03494bacf7279745425e2fa18 diff --git a/hacks/glx/queens.c b/hacks/glx/queens.c index ba14cc7b..3c671aff 100644 --- a/hacks/glx/queens.c +++ b/hacks/glx/queens.c @@ -6,7 +6,7 @@ * * version 1.0 - May 10, 2002 * - * Copyright (C) 2002 Blair Tennessy (tennessb@unbc.ca) + * Copyright (C) 2002 Blair Tennessy (tennessy@cs.ubc.ca) * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -17,21 +17,12 @@ * implied warranty. */ -#include - #ifdef STANDALONE -# define PROGCLASS "Queens" -# define HACK_INIT init_queens -# define HACK_DRAW draw_queens -# define HACK_RESHAPE reshape_queens -# define HACK_HANDLE_EVENT queens_handle_event -# define EVENT_MASK PointerMotionMask -# define queens_opts xlockmore_opts - -#define DEFAULTS "*delay: 20000 \n" \ - "*showFPS: False \n" \ - "*wireframe: False \n" \ +#define DEFAULTS "*delay: 20000 \n" \ + "*showFPS: False \n" \ + "*wireframe: False \n" \ +# define refresh_queens 0 # include "xlockmore.h" #else @@ -40,26 +31,26 @@ #ifdef USE_GL -#include #include "gltrackball.h" #undef countof #define countof(x) (sizeof((x))/sizeof((*x))) static XrmOptionDescRec opts[] = { - {"+rotate", ".queens.rotate", XrmoptionNoArg, (caddr_t) "false" }, - {"-rotate", ".queens.rotate", XrmoptionNoArg, (caddr_t) "true" }, -/* {"-white", ".queens.white", XrmoptionSepArg, (cadd_t) NULL }, */ -/* {"-black", ".queens.white", XrmoptionSepArg, (cadd_t) NULL }, */ + {"+rotate", ".queens.rotate", XrmoptionNoArg, "false" }, + {"-rotate", ".queens.rotate", XrmoptionNoArg, "true" }, + {"+flat", ".queens.flat", XrmoptionNoArg, "false" }, + {"-flat", ".queens.flat", XrmoptionNoArg, "true" }, }; -int rotate, wire, clearbits; +static int rotate, wire, clearbits, flat; static argtype vars[] = { - {(caddr_t *) &rotate, "rotate", "Rotate", "True", t_Bool}, + {&rotate, "rotate", "Rotate", "True", t_Bool}, + {&flat, "flat", "Flat", "False", t_Bool}, }; -ModeSpecOpt queens_opts = {countof(opts), opts, countof(vars), vars, NULL}; +ENTRYPOINT ModeSpecOpt queens_opts = {countof(opts), opts, countof(vars), vars, NULL}; #ifdef USE_MODULES ModStruct queens_description = @@ -70,65 +61,71 @@ ModStruct queens_description = #endif +#define NONE 0 +#define QUEEN 1 +#define MINBOARD 5 +#define MAXBOARD 10 +#define COLORSETS 5 + typedef struct { GLXContext *glx_context; Window window; trackball_state *trackball; Bool button_down_p; -} Queenscreen; + GLfloat position[4]; -static Queenscreen *qs = NULL; + int board[MAXBOARD][MAXBOARD]; + int steps, colorset, BOARDSIZE; + double theta; -#include -#include -#include -#include +} Queenscreen; -#ifndef M_PI -#define M_PI 3.14159265 -#endif - -#define NONE 0 -#define QUEEN 1 -#define MINBOARD 5 -#define MAXBOARD 10 -#define COLORSETS 3 +static Queenscreen *qss = NULL; /* definition of white/black colors */ -GLfloat colors[COLORSETS][2][3] = +static const GLfloat colors[COLORSETS][2][3] = { + {{0.43, 0.54, 0.76}, {0.8, 0.8, 0.8}}, {{0.5, 0.7, 0.9}, {0.2, 0.3, 0.6}}, {{0.53725490196, 0.360784313725, 0.521568627451}, {0.6, 0.6, 0.6}}, - {{1.0, 0.5, 0.0}, {0.5, 0.5, 0.5}}, + {{0.15, 0.77, 0.54}, {0.5, 0.5, 0.5}}, + {{0.9, 0.45, 0.0}, {0.5, 0.5, 0.5}}, }; -int board[MAXBOARD][MAXBOARD]; -int steps = 0, colorset = 0, BOARDSIZE = 8; /* 8 cuz its classic */ - -Bool +ENTRYPOINT Bool queens_handle_event (ModeInfo *mi, XEvent *event) { - Queenscreen *c = &qs[MI_SCREEN(mi)]; + Queenscreen *qs = &qss[MI_SCREEN(mi)]; if (event->xany.type == ButtonPress && - event->xbutton.button & Button1) + event->xbutton.button == Button1) { - c->button_down_p = True; - gltrackball_start (c->trackball, + qs->button_down_p = True; + gltrackball_start (qs->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) + event->xbutton.button == Button1) { - c->button_down_p = False; + qs->button_down_p = False; + return True; + } + else if (event->xany.type == ButtonPress && + (event->xbutton.button == Button4 || + event->xbutton.button == Button5 || + event->xbutton.button == Button6 || + event->xbutton.button == Button7)) + { + gltrackball_mousewheel (qs->trackball, event->xbutton.button, 5, + !event->xbutton.state); return True; } else if (event->xany.type == MotionNotify && - c->button_down_p) + qs->button_down_p) { - gltrackball_track (c->trackball, + gltrackball_track (qs->trackball, event->xmotion.x, event->xmotion.y, MI_WIDTH (mi), MI_HEIGHT (mi)); return True; @@ -140,62 +137,67 @@ queens_handle_event (ModeInfo *mi, XEvent *event) /* returns true if placing a queen on column c causes a conflict */ -int conflictsCols(int c) { +static int conflictsCols(Queenscreen *qs, int c) +{ int i; - for(i = 0; i < BOARDSIZE; ++i) - if(board[i][c]) + for(i = 0; i < qs->BOARDSIZE; ++i) + if(qs->board[i][c]) return 1; return 0; } /* returns true if placing a queen on (r,c) causes a diagonal conflict */ -int conflictsDiag(int r, int c) { +static int conflictsDiag(Queenscreen *qs, int r, int c) +{ int i; /* positive slope */ int n = r < c ? r : c; - for(i = 0; i < BOARDSIZE-abs(r-c); ++i) - if(board[r-n+i][c-n+i]) + for(i = 0; i < qs->BOARDSIZE-abs(r-c); ++i) + if(qs->board[r-n+i][c-n+i]) return 1; /* negative slope */ - n = r < BOARDSIZE - (c+1) ? r : BOARDSIZE - (c+1); - for(i = 0; i < BOARDSIZE-abs(BOARDSIZE - (1+r+c)); ++i) - if(board[r-n+i][c+n-i]) + n = r < qs->BOARDSIZE - (c+1) ? r : qs->BOARDSIZE - (c+1); + for(i = 0; i < qs->BOARDSIZE-abs(qs->BOARDSIZE - (1+r+c)); ++i) + if(qs->board[r-n+i][c+n-i]) return 1; return 0; } /* returns true if placing a queen at (r,c) causes a conflict */ -int conflicts(int r, int c) { - return !conflictsCols(c) ? conflictsDiag(r, c) : 1; +static int conflicts(Queenscreen *qs, int r, int c) +{ + return !conflictsCols(qs, c) ? conflictsDiag(qs, r, c) : 1; } /* clear board */ -void blank(void) { +static void blank(Queenscreen *qs) +{ int i, j; for(i = 0; i < MAXBOARD; ++i) for(j = 0; j < MAXBOARD; ++j) - board[i][j] = NONE; + qs->board[i][j] = NONE; } /* recursively determine solution */ -int findSolution(int row, int col) { - if(row == BOARDSIZE) +static int findSolution(Queenscreen *qs, int row, int col) +{ + if(row == qs->BOARDSIZE) return 1; - while(col < BOARDSIZE) { - if(!conflicts(row, col)) { - board[row][col] = 1; + while(col < qs->BOARDSIZE) { + if(!conflicts(qs, row, col)) { + qs->board[row][col] = 1; - if(findSolution(row+1, 0)) + if(findSolution(qs, row+1, 0)) return 1; - board[row][col] = 0; + qs->board[row][col] = 0; } ++col; @@ -205,103 +207,190 @@ int findSolution(int row, int col) { } /** driver for finding solution */ -void go(void) { while(!findSolution(0, random()%BOARDSIZE)); } +static void go(Queenscreen *qs) { while(!findSolution(qs, 0, random()%qs->BOARDSIZE)); } + +/* lighting variables */ +static const GLfloat front_shininess[] = {60.0}; +static const GLfloat front_specular[] = {0.4, 0.4, 0.4, 1.0}; +static const GLfloat ambient[] = {0.3, 0.3, 0.3, 1.0}; +static const GLfloat diffuse[] = {0.8, 0.8, 0.8, 1.0}; /* configure lighting */ -void setup_lights(void) { - GLfloat position[] = { 4.0, 8.0, 4.0, 1.0 }; +static void setup_lights(Queenscreen *qs) +{ + /* setup twoside lighting */ + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, qs->position); glEnable(GL_LIGHTING); - glLightfv(GL_LIGHT0, GL_POSITION, position); glEnable(GL_LIGHT0); + + /* setup material properties */ + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } +#define checkImageWidth 8 +#define checkImageHeight 8 +/*static GLubyte checkImage[checkImageWidth][checkImageHeight][3];*/ + /* return alpha value for fading */ -GLfloat findAlpha(void) { - return steps < 128 ? steps/128.0 : steps < 512-128 ? 1.0 : (512-steps)/128.0; +static GLfloat findAlpha(Queenscreen *qs) +{ + return qs->steps < 128 ? qs->steps/128.0 : qs->steps < 1024-128 ?1.0:(1024-qs->steps)/128.0; } /* draw pieces */ -void drawPieces(void) { +static void drawPieces(Queenscreen *qs) +{ int i, j; - for(i = 0; i < BOARDSIZE; ++i) { - for(j = 0; j < BOARDSIZE; ++j) { - if(board[i][j]) { - glColor3fv(colors[colorset][i%2]); + for(i = 0; i < qs->BOARDSIZE; ++i) { + for(j = 0; j < qs->BOARDSIZE; ++j) { + if(qs->board[i][j]) { + glColor3fv(colors[qs->colorset][i%2]); glCallList(QUEEN); } glTranslatef(1.0, 0.0, 0.0); } - glTranslatef(-1.0*BOARDSIZE, 0.0, 1.0); + glTranslatef(-1.0*qs->BOARDSIZE, 0.0, 1.0); } } -/* draw board */ -void drawBoard(void) { +/** reflectionboard */ +static void draw_reflections(Queenscreen *qs) +{ int i, j; + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glColorMask(0,0,0,0); + glDisable(GL_CULL_FACE); + + glDisable(GL_DEPTH_TEST); glBegin(GL_QUADS); - for(i = 0; i < BOARDSIZE; ++i) - for(j = 0; j < BOARDSIZE; ++j) { - int par = (i-j+BOARDSIZE)%2; - glColor3fv(colors[colorset][par]); - glNormal3f(0.0, 1.0, 0.0); + /* only draw white squares */ + for(i = 0; i < qs->BOARDSIZE; ++i) { + for(j = (qs->BOARDSIZE+i) % 2; j < qs->BOARDSIZE; j += 2) { glVertex3f(i, 0.0, j + 1.0); glVertex3f(i + 1.0, 0.0, j + 1.0); glVertex3f(i + 1.0, 0.0, j); glVertex3f(i, 0.0, j); + } + } + glEnd(); + glEnable(GL_DEPTH_TEST); - /* draw the bottom, too */ - glNormal3f(0.0, -1.0, 0.0); - glVertex3f(i, 0.0, j); - glVertex3f(i + 1.0, 0.0, j); - glVertex3f(i + 1.0, 0.0, j + 1.0); + glColorMask(1, 1, 1, 1); + glStencilFunc(GL_EQUAL, 1, 1); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + glPushMatrix(); + glScalef(1.0, -1.0, 1.0); + glTranslatef(0.5, 0.001, 0.5); + glLightfv(GL_LIGHT0, GL_POSITION, qs->position); + drawPieces(qs); + glPopMatrix(); + glDisable(GL_STENCIL_TEST); + + /* replace lights */ + glLightfv(GL_LIGHT0, GL_POSITION, qs->position); + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glColorMask(1,1,1,1); +} + +/* draw board */ +static void drawBoard(Queenscreen *qs) +{ + int i, j; + + glBegin(GL_QUADS); + + for(i = 0; i < qs->BOARDSIZE; ++i) + for(j = 0; j < qs->BOARDSIZE; ++j) { + int par = (i-j+qs->BOARDSIZE)%2; + glColor4f(colors[qs->colorset][par][0], + colors[qs->colorset][par][1], + colors[qs->colorset][par][2], + 0.70); + glNormal3f(0.0, 1.0, 0.0); glVertex3f(i, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j + 1.0); + glVertex3f(i + 1.0, 0.0, j); + glVertex3f(i, 0.0, j); } glEnd(); } -double theta = 0.0; - -void display(Queenscreen *c) { +static void display(Queenscreen *qs) +{ glClear(clearbits); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.8/(0.01+findAlpha())); + /* setup light attenuation */ + glEnable(GL_COLOR_MATERIAL); + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.8/(0.01+findAlpha(qs))); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.06); - /** setup perspectif */ - glTranslatef(0.0, 0.0, -1.5*BOARDSIZE); + /** setup perspective */ + glTranslatef(0.0, 0.0, -1.5*qs->BOARDSIZE); glRotatef(30.0, 1.0, 0.0, 0.0); - gltrackball_rotate (c->trackball); - glRotatef(theta*100, 0.0, 1.0, 0.0); - glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE); + gltrackball_rotate (qs->trackball); + glRotatef(qs->theta*100, 0.0, 1.0, 0.0); + glTranslatef(-0.5*qs->BOARDSIZE, 0.0, -0.5*qs->BOARDSIZE); + + /* find light positions */ + qs->position[0] = qs->BOARDSIZE/2.0 + qs->BOARDSIZE/1.4*-sin(qs->theta*100*M_PI/180.0); + qs->position[2] = qs->BOARDSIZE/2.0 + qs->BOARDSIZE/1.4*cos(qs->theta*100*M_PI/180.0); + qs->position[1] = 6.0; + + if(!wire) { + glEnable(GL_LIGHTING); + glLightfv(GL_LIGHT0, GL_POSITION, qs->position); + glEnable(GL_LIGHT0); + } + + /* draw reflections */ + if(!wire) { + draw_reflections(qs); + glEnable(GL_BLEND); + } + drawBoard(qs); + if(!wire) + glDisable(GL_BLEND); + + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.1); - drawBoard(); - glTranslatef(0.5, 0.01, 0.5); - drawPieces(); + glTranslatef(0.5, 0.0, 0.5); + drawPieces(qs); - if (!c->button_down_p) - theta += .002; + /* rotate camera */ + if(!qs->button_down_p) + qs->theta += .002; /* zero out board, find new solution of size MINBOARD <= i <= MAXBOARD */ - if(++steps == 512) { - steps = 0; - blank(); - BOARDSIZE = MINBOARD + (random() % (MAXBOARD - MINBOARD + 1)); - colorset = (colorset+1)%COLORSETS; - go(); + if(++qs->steps == 1024) { + qs->steps = 0; + blank(qs); + qs->BOARDSIZE = MINBOARD + (random() % (MAXBOARD - MINBOARD + 1)); + qs->colorset = (qs->colorset+1)%COLORSETS; + go(qs); } } -int schunks = 15; -GLfloat spidermodel[][3] = +static const GLfloat spidermodel[][3] = { {0.48, 0.48, 0.22}, {0.48, 0.34, 0.18}, @@ -320,10 +409,12 @@ GLfloat spidermodel[][3] = {0.07, 0.00, 0.12}, }; + #define EPSILON 0.001 /** draws cylindermodel */ -void draw_model(int chunks, GLfloat model[][3], int r) { +static void draw_model(int chunks, const GLfloat model[][3], int r) +{ int i = 0; GLUquadricObj *quadric = gluNewQuadric(); glPushMatrix(); @@ -338,7 +429,8 @@ void draw_model(int chunks, GLfloat model[][3], int r) { glPopMatrix(); } -void reshape_queens(ModeInfo *mi, int width, int height) { +ENTRYPOINT void reshape_queens(ModeInfo *mi, int width, int height) +{ GLfloat h = (GLfloat) height / (GLfloat) width; glViewport(0,0, width, height); glMatrixMode(GL_PROJECTION); @@ -347,28 +439,34 @@ void reshape_queens(ModeInfo *mi, int width, int height) { glMatrixMode(GL_MODELVIEW); } -void init_queens(ModeInfo *mi) { +ENTRYPOINT void init_queens(ModeInfo *mi) +{ int screen = MI_SCREEN(mi); - Queenscreen *c; + Queenscreen *qs; wire = MI_IS_WIREFRAME(mi); - if(!qs && - !(qs = (Queenscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Queenscreen)))) + if(!qss && + !(qss = (Queenscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Queenscreen)))) return; - c = &qs[screen]; - c->window = MI_WINDOW(mi); - c->trackball = gltrackball_init (); + qs = &qss[screen]; + qs->window = MI_WINDOW(mi); + qs->trackball = gltrackball_init (); + + qs->BOARDSIZE = 8; /* 8 cuz its classic */ - if((c->glx_context = init_GL(mi))) + if((qs->glx_context = init_GL(mi))) reshape_queens(mi, MI_WIDTH(mi), MI_HEIGHT(mi)); else MI_CLEARWINDOW(mi); glClearColor(0.0, 0.0, 0.0, 0.0); - glNewList(1, GL_COMPILE); - draw_model(schunks, spidermodel, 24); + glNewList(QUEEN, GL_COMPILE); + draw_model(countof(spidermodel), spidermodel, 24); glEndList(); + + if(flat) + glShadeModel(GL_FLAT); clearbits = GL_COLOR_BUFFER_BIT; @@ -376,9 +474,10 @@ void init_queens(ModeInfo *mi) { glEnable(GL_COLOR_MATERIAL); if(!wire) { - setup_lights(); + setup_lights(qs); glEnable(GL_DEPTH_TEST); clearbits |= GL_DEPTH_BUFFER_BIT; + clearbits |= GL_STENCIL_BUFFER_BIT; glEnable(GL_CULL_FACE); glCullFace(GL_BACK); } @@ -386,31 +485,36 @@ void init_queens(ModeInfo *mi) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); /* find a solution */ - go(); + go(qs); } -void draw_queens(ModeInfo *mi) { - Queenscreen *c = &qs[MI_SCREEN(mi)]; +ENTRYPOINT void draw_queens(ModeInfo *mi) +{ + Queenscreen *qs = &qss[MI_SCREEN(mi)]; Window w = MI_WINDOW(mi); Display *disp = MI_DISPLAY(mi); - if(!c->glx_context) + if(!qs->glx_context) return; - glXMakeCurrent(disp, w, *(c->glx_context)); + glXMakeCurrent(disp, w, *(qs->glx_context)); - display(c); + display(qs); if(mi->fps_p) do_fps(mi); glFinish(); glXSwapBuffers(disp, w); } -void release_queens(ModeInfo *mi) { - if(qs) - free((void *) qs); +ENTRYPOINT void release_queens(ModeInfo *mi) +{ + if(qss) + free((void *) qss); + qss = 0; - FreeAllGL(MI); + FreeAllGL(mi); } +XSCREENSAVER_MODULE ("Queens", queens) + #endif