X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fqueens.c;h=e6e0644660cbaab296a14ab7cc13b922e8c5217d;hp=42ac6e2c66eb44faf96558a4e4027265ebc37542;hb=ffd8c0873576a9e3065696a624dce6b766b77062;hpb=13dbc569cdc6e29019722c0ef9b932a925efbcad diff --git a/hacks/glx/queens.c b/hacks/glx/queens.c index 42ac6e2c..e6e06446 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 @@ -47,14 +47,17 @@ #define countof(x) (sizeof((x))/sizeof((*x))) static XrmOptionDescRec opts[] = { - {"+rotate", ".queens.rotate", XrmoptionNoArg, (caddr_t) "false" }, - {"-rotate", ".queens.rotate", XrmoptionNoArg, (caddr_t) "true" }, + {"+rotate", ".queens.rotate", XrmoptionNoArg, "false" }, + {"-rotate", ".queens.rotate", XrmoptionNoArg, "true" }, + {"+flat", ".queens.flat", XrmoptionNoArg, "false" }, + {"-flat", ".queens.flat", XrmoptionNoArg, "true" }, }; -int rotate; +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}; @@ -90,13 +93,21 @@ static Queenscreen *qs = NULL; #define QUEEN 1 #define MINBOARD 5 #define MAXBOARD 10 +#define COLORSETS 5 /* definition of white/black colors */ -GLfloat colors[2][3] = { {0.5, 0.7, 0.9}, - {0.2, 0.3, 0.6} }; +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}}, + {{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 work = 0, vb = 0, steps = 0, BOARDSIZE = 8; /* 8 cuz its classic */ +int steps = 0, colorset = 0, BOARDSIZE = 8; /* 8 cuz its classic */ +double theta = 0.0; Bool queens_handle_event (ModeInfo *mi, XEvent *event) @@ -177,20 +188,18 @@ void blank(void) { } /* recursively determine solution */ -int findSolution(int row) { - int col = 0; - +int findSolution(int row, int col) { if(row == BOARDSIZE) return 1; while(col < BOARDSIZE) { if(!conflicts(row, col)) { - board[row][col] = QUEEN; + board[row][col] = 1; - if(findSolution(row+1)) - return 1; + if(findSolution(row+1, 0)) + return 1; - board[row][col] = NONE; + board[row][col] = 0; } ++col; @@ -199,21 +208,42 @@ int findSolution(int row) { return 0; } -/* driver for finding solution */ -void go(void) { findSolution(0); } +/** driver for finding solution */ +void go(void) { while(!findSolution(0, random()%BOARDSIZE)); } + +/* lighting variables */ +GLfloat front_shininess[] = {60.0}; +GLfloat front_specular[] = {0.4, 0.4, 0.4, 1.0}; +GLfloat ambient[] = {0.3, 0.3, 0.3, 1.0}; +GLfloat diffuse[] = {0.8, 0.8, 0.8, 1.0}; +GLfloat position[] = { 0.0, 5.0, 5.0, 1.0 }; +GLfloat lmodel_ambient[] = {0.6, 0.6, 0.6, 1.0}; +GLfloat lmodel_twoside[] = {GL_TRUE}; /* configure lighting */ void setup_lights(void) { - GLfloat position[] = { 4.0, 8.0, 4.0, 1.0 }; - glEnable(GL_LIGHTING); + /* setup twoside lighting */ + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_POSITION, position); + glEnable(GL_LIGHTING); 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 +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; + return steps < 128 ? steps/128.0 : steps < 1024-128 ?1.0:(1024-steps)/128.0; } /* draw pieces */ @@ -223,7 +253,7 @@ void drawPieces(void) { for(i = 0; i < BOARDSIZE; ++i) { for(j = 0; j < BOARDSIZE; ++j) { if(board[i][j]) { - glColor4f(colors[i%2][0], colors[i%2][1], colors[i%2][2], findAlpha()); + glColor3fv(colors[colorset][i%2]); glCallList(QUEEN); } @@ -234,179 +264,167 @@ void drawPieces(void) { } } +/** reflectionboard */ +void draw_reflections(void) { + 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); + + /* only draw white squares */ + for(i = 0; i < BOARDSIZE; ++i) { + for(j = (BOARDSIZE+i) % 2; j < 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); + + 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, position); + drawPieces(); + glPopMatrix(); + glDisable(GL_STENCIL_TEST); + + /* replace lights */ + glLightfv(GL_LIGHT0, GL_POSITION, position); + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glColorMask(1,1,1,1); +} + /* draw board */ -void drawBoard(int wire) { +void drawBoard(void) { int i, j; - if (!wire) glBegin(GL_QUADS); + glBegin(GL_QUADS); for(i = 0; i < BOARDSIZE; ++i) for(j = 0; j < BOARDSIZE; ++j) { int par = (i-j+BOARDSIZE)%2; - glColor4f(colors[par][0], colors[par][1], colors[par][2], findAlpha()); + glColor4f(colors[colorset][par][0], + colors[colorset][par][1], + colors[colorset][par][2], + 0.70); glNormal3f(0.0, 1.0, 0.0); - if (wire) glBegin(GL_LINE_LOOP); - glVertex3f(j - 0.5, -0.01, i - 0.5); - glVertex3f(j + 0.5, -0.01, i - 0.5); - glVertex3f(j + 0.5, -0.01, i + 0.5); - glVertex3f(j - 0.5, -0.01, i + 0.5); - if (wire) glEnd(); + 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); } - if (!wire) glEnd(); + glEnd(); } -double theta = 0.0; - -void display(Queenscreen *c, int wire) { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +void display(Queenscreen *c) { + glClear(clearbits); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - gluLookAt(0.0, 1.0+(0.8*fabs(sin(theta)))*10.0, -1.2*BOARDSIZE, - 0.0, 1.0, 0.0, - 0.0, 0.0, 1.0); - glScalef(1, -1, 1); - gltrackball_rotate (c->trackball); /* Apply mouse-based camera position */ - glScalef(1, -1, 1); + /* setup light attenuation */ + glEnable(GL_COLOR_MATERIAL); + glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.8/(0.01+findAlpha())); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.06); + /** setup perspective */ + 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); - glTranslatef(-0.5 * (BOARDSIZE-1), 0.0, -0.5 * (BOARDSIZE-1)); + glTranslatef(-0.5*BOARDSIZE, 0.0, -0.5*BOARDSIZE); + + /* find light positions */ + position[0] = BOARDSIZE/2.0 + BOARDSIZE/1.4*-sin(theta*100*M_PI/180.0); + position[2] = BOARDSIZE/2.0 + BOARDSIZE/1.4*cos(theta*100*M_PI/180.0); + position[1] = 6.0; - if (!wire) { + if(!wire) { glEnable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); + glLightfv(GL_LIGHT0, GL_POSITION, position); + glEnable(GL_LIGHT0); + } + + /* draw reflections */ + if(!wire) { + draw_reflections(); glEnable(GL_BLEND); } + drawBoard(); + if(!wire) + glDisable(GL_BLEND); - drawBoard(wire); - glTranslatef(0.0, 0.01, 0.0); - drawPieces(); + glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.1); - glDisable(GL_COLOR_MATERIAL); - glDisable(GL_BLEND); - glDisable(GL_LIGHTING); + glTranslatef(0.5, 0.0, 0.5); + drawPieces(); - theta += .002; + /* rotate camera */ + if(!c->button_down_p) + theta += .002; /* zero out board, find new solution of size MINBOARD <= i <= MAXBOARD */ - if(++steps == 512) { + if(++steps == 1024) { steps = 0; blank(); BOARDSIZE = MINBOARD + (random() % (MAXBOARD - MINBOARD + 1)); + colorset = (colorset+1)%COLORSETS; go(); } } -#define piece_size 0.1 -#define EPSILON 0.001 - -/* Make a revolved piece */ -void revolve_line(double *trace_r, double *trace_h, double max_iheight, - int rot, int wire) { - double theta, norm_theta, sin_theta, cos_theta; - double norm_ptheta = 0.0, sin_ptheta = 0.0, cos_ptheta = 1.0; - double radius, pradius; - double max_height = max_iheight, height, pheight; - double dx, dy, len; - int npoints, p; - double dtheta = (2.0*M_PI) / rot; - - /* Get the number of points */ - for(npoints = 0; - fabs(trace_r[npoints]) > EPSILON || fabs(trace_h[npoints]) > EPSILON; - ++npoints); - - /* If less than two points, can not revolve */ - if(npoints < 2) - return; - - /* If the max_height hasn't been defined, find it */ - if(max_height < EPSILON) - for(p = 0; p < npoints; ++p) - if(max_height < trace_h[p]) - max_height = trace_h[p]; - - /* Draw the revolution */ - for(theta = dtheta; rot > 0; --rot) { - sin_theta = sin(theta); - cos_theta = cos(theta); - norm_theta = theta / (2.0 * M_PI); - pradius = trace_r[0] * piece_size; - pheight = trace_h[0] * piece_size; - - for(p = 0; p < npoints; ++p) { - radius = trace_r[p] * piece_size; - height = trace_h[p] * piece_size; - - /* Get the normalized lengths of the normal vector */ - dx = radius - pradius; - dy = height - pheight; - len = sqrt(dx*dx + dy*dy); - dx /= len; - dy /= len; - - /* If only triangles required */ - if (fabs(radius) < EPSILON) { - glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES); - - glNormal3f(dy * sin_ptheta, -dx, dy * cos_ptheta); - glTexCoord2f(norm_ptheta, pheight / max_height); - glVertex3f(pradius * sin_ptheta, pheight, pradius * cos_ptheta); - - glNormal3f(dy * sin_theta, -dx, dy * cos_theta); - glTexCoord2f(norm_theta, pheight / max_height); - glVertex3f(pradius * sin_theta, pheight, pradius * cos_theta); - - glTexCoord2f(0.5 * (norm_theta + norm_ptheta), - height / max_height); - glVertex3f(0.0, height, 0.0); - - glEnd(); - } - - else { - glBegin(wire ? GL_LINE_LOOP : GL_QUADS); - - glNormal3f(dy * sin_ptheta, -dx, dy * cos_ptheta); - glTexCoord2f(norm_ptheta, pheight / max_height); - glVertex3f(pradius * sin_ptheta, pheight, pradius * cos_ptheta); - - glNormal3f(dy * sin_theta, -dx, dy * cos_theta); - glTexCoord2f(norm_theta, pheight / max_height); - glVertex3f(pradius * sin_theta, pheight, pradius * cos_theta); - - glTexCoord2f(norm_theta, height / max_height); - glVertex3f(radius * sin_theta, height, radius * cos_theta); - - glNormal3f(dy * sin_ptheta, -dx, dy * cos_ptheta); - glTexCoord2f(norm_ptheta, height / max_height); - glVertex3f(radius * sin_ptheta, height, radius * cos_ptheta); +int schunks = 15; +GLfloat spidermodel[][3] = + { + {0.48, 0.48, 0.22}, + {0.48, 0.34, 0.18}, + {0.34, 0.34, 0.10}, + {0.34, 0.18, 0.30}, + {0.18, 0.14, 0.38}, + {0.14, 0.29, 0.01}, + {0.29, 0.18, 0.18}, + {0.18, 0.18, 0.16}, + {0.18, 0.20, 0.26}, + {0.20, 0.27, 0.14}, + {0.27, 0.24, 0.08}, + {0.24, 0.17, 0.00}, + {0.17, 0.095, 0.08}, + {0.095, 0.07, 0.00}, + {0.07, 0.00, 0.12}, + }; - glEnd(); - } - - pradius = radius; - pheight = height; - } +#define EPSILON 0.001 - sin_ptheta = sin_theta; - cos_ptheta = cos_theta; - norm_ptheta = norm_theta; - theta += dtheta; +/** draws cylindermodel */ +void draw_model(int chunks, GLfloat model[][3], int r) { + int i = 0; + GLUquadricObj *quadric = gluNewQuadric(); + glPushMatrix(); + glRotatef(-90.0, 1.0, 0.0, 0.0); + + for(i = 0; i < chunks; ++i) { + if(model[i][0] > EPSILON || model[i][1] > EPSILON) + gluCylinder(quadric, model[i][0], model[i][1], model[i][2], r, 1); + glTranslatef(0.0, 0.0, model[i][2]); } -} - -void draw_queen(int wire) { - double trace_r[] = - { 4.8, 4.8, 3.4, 3.4, 1.8, 1.4, 2.9, 1.8, 1.8, 2.0, - 2.7, 2.4, 1.7, 0.95, 0.7, 0.0, 0.0 }; /*, 0.9, 0.7, 0.0, 0.0};*/ - double trace_h[] = - { 0.0, 2.2, 4.0, 5.0, 8.0, 11.8, 11.8, 13.6, 15.2, 17.8, - 19.2, 20.0, 20.0, 20.8, 20.8, 22.0, 0.0 };/*,21.4, 22.0, 22.0, 0.0 };*/ - - revolve_line(trace_r, trace_h, 0.0, 8, wire); + + glPopMatrix(); } void reshape_queens(ModeInfo *mi, int width, int height) { @@ -419,12 +437,9 @@ void reshape_queens(ModeInfo *mi, int width, int height) { } void init_queens(ModeInfo *mi) { - GLfloat mat_shininess[] = { 90.0 }; - GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; - int screen = MI_SCREEN(mi); - int wire = MI_IS_WIREFRAME(mi); Queenscreen *c; + wire = MI_IS_WIREFRAME(mi); if(!qs && !(qs = (Queenscreen *) calloc(MI_NUM_SCREENS(mi), sizeof(Queenscreen)))) @@ -440,22 +455,28 @@ void init_queens(ModeInfo *mi) { MI_CLEARWINDOW(mi); glClearColor(0.0, 0.0, 0.0, 0.0); - - setup_lights(); - glNewList(1, GL_COMPILE); - draw_queen(wire); + glNewList(QUEEN, GL_COMPILE); + draw_model(schunks, spidermodel, 24); glEndList(); - if (!wire) { - glColorMaterial(GL_FRONT, GL_DIFFUSE); + if(flat) + glShadeModel(GL_FLAT); + + clearbits = GL_COLOR_BUFFER_BIT; - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + glColorMaterial(GL_FRONT, GL_DIFFUSE); + glEnable(GL_COLOR_MATERIAL); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glShadeModel(GL_SMOOTH); + if(!wire) { + setup_lights(); glEnable(GL_DEPTH_TEST); + clearbits |= GL_DEPTH_BUFFER_BIT; + clearbits |= GL_STENCIL_BUFFER_BIT; + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); } + else + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); /* find a solution */ go(); @@ -471,7 +492,7 @@ void draw_queens(ModeInfo *mi) { glXMakeCurrent(disp, w, *(c->glx_context)); - display(c, MI_IS_WIREFRAME(mi)); + display(c); if(mi->fps_p) do_fps(mi); glFinish();