*
* 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
#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};
#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)
}
/* 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;
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 */
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);
}
}
}
+/** 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) {
}
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))))
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();
glXMakeCurrent(disp, w, *(c->glx_context));
- display(c, MI_IS_WIREFRAME(mi));
+ display(c);
if(mi->fps_p) do_fps(mi);
glFinish();