This OpenGL program allows a user to pick (select) a pawn and then select a new location to move the pawn object.
board.cc:
// Peter Bui // CSE 40166 Computer Graphics (Fall 2010) // Example 4: pawn board #include <cmath> #include <cstdio> #include <cstdlib> #ifdef __APPLE__ #include <GLUT/glut.h> #else #include <GL/glut.h> #endif // Pawn data structure --------------------------------------------------------- struct pawn { size_t row; size_t column; int state; }; // Constants ------------------------------------------------------------------- enum PAWN_STATE { PAWN_STATE_UNSELECTED, PAWN_STATE_SELECTED, PAWN_STATE_MAX, }; enum DISPLAY_LISTS { DL_CELL, DL_PAWN, DL_BOX, DL_MAX }; static const GLfloat CellColors[][3] = { {0.0, 0.0, 0.0}, {1.0, 1.0, 1.0} }; static const GLfloat PawnColors[][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} }; #define SBSIZE 128 // Global variables ------------------------------------------------------------ static GLuint DisplayListsBase; static size_t WindowWidth = 640; static size_t WindowHeight = 480; static size_t BoardRows = 8; static size_t BoardColumns = 8; static struct pawn Pawn = { 0, 0, PAWN_STATE_UNSELECTED }; static GLuint PawnName = (BoardRows * BoardColumns) + 1; static GLuint SelectBuffer[SBSIZE]; static GLuint PickLimit = 5; static GLuint CursorX, CursorY; static GLenum Mode = GL_RENDER; static GLuint FrameRate = 60; // Draw cell ------------------------------------------------------------------- void draw_cell() { glBegin(GL_QUADS); { glVertex2f(0.0, 0.0); glVertex2f(0.0, 1.0); glVertex2f(1.0, 1.0); glVertex2f(1.0, 0.0); } glEnd(); } // Draw pawn ------------------------------------------------------------------- void draw_pawn() { glBegin(GL_QUADS); { glVertex2f(-0.5, -0.5); glVertex2f( 0.5, -0.5); glVertex2f( 0.5, 0.0); glVertex2f(-0.5, 0.0); } glEnd(); glBegin(GL_TRIANGLE_FAN); { double ox = 0.0, oy = 0.25, radius = 0.25; int triangles = 32; glVertex2f(ox, oy); for (int i = 0; i <= triangles; i++) { double angle = i * 2.0 * M_PI / triangles; glVertex2f(ox + radius * cos(angle), oy + radius * sin(angle)); } } glEnd(); } // Draw box -------------------------------------------------------------------- void draw_box() { glPushAttrib(GL_LINE_BIT); glLineWidth(4.0); glBegin(GL_LINE_LOOP); { glVertex2f(0.0, 0.0); glVertex2f(0.0, 1.0); glVertex2f(1.0, 1.0); glVertex2f(1.0, 0.0); } glEnd(); glPopAttrib(); } // Draw scene ------------------------------------------------------------------ void draw_scene() { size_t cc = CursorX * BoardColumns / WindowWidth; size_t cr = (WindowHeight - CursorY) * BoardRows / WindowHeight; for (size_t r = 0; r < BoardRows; r++) { glPushName(r); for (size_t c = 0; c < BoardColumns; c++) { glPushName(c); glPushMatrix(); glColor3fv(CellColors[(c + (r % 2)) % 2]); glTranslatef(c, r, 0.0); glCallList(DisplayListsBase + DL_CELL); if (Pawn.row == r && Pawn.column == c) { glPushName(PawnName); glPushMatrix(); glColor3fv(PawnColors[Pawn.state]); glTranslatef(0.5, 0.5, 0.0); glScalef(0.5, 0.5, 1.0); glCallList(DisplayListsBase + DL_PAWN); glPopMatrix(); glPopName(); } if (Pawn.state == PAWN_STATE_SELECTED) { if (cc == c && cr == r) { glColor3fv(PawnColors[Pawn.state]); glCallList(DisplayListsBase + DL_BOX); } } glPopMatrix(); glPopName(); } glPopName(); } } // Initialize scene ------------------------------------------------------------ void init_scene() { glClearColor(1.0, 1.0, 1.0, 1.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, BoardRows, 0, BoardColumns); glMatrixMode(GL_MODELVIEW); } // Make display lists ---------------------------------------------------------- void make_display_lists() { DisplayListsBase = glGenLists(DL_MAX); glNewList(DisplayListsBase + DL_CELL, GL_COMPILE); { glPushMatrix(); draw_cell(); glPopMatrix(); } glEndList(); glNewList(DisplayListsBase + DL_PAWN, GL_COMPILE); { glPushMatrix(); draw_pawn(); glPopMatrix(); } glEndList(); glNewList(DisplayListsBase + DL_BOX, GL_COMPILE); { glPushMatrix(); draw_box(); glPopMatrix(); } glEndList(); } // Picking functions ----------------------------------------------------------- void start_picking() { GLint viewport[4]; glSelectBuffer(SBSIZE, SelectBuffer); glGetIntegerv(GL_VIEWPORT, viewport); glRenderMode(GL_SELECT); glInitNames(); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix(CursorX, viewport[3] - CursorY, PickLimit, PickLimit, viewport); gluOrtho2D(0, BoardRows, 0, BoardColumns); glMatrixMode(GL_MODELVIEW); } void process_hits(GLint hits, GLuint *buffer) { GLuint names; GLuint *bp = buffer; for (GLint i = 0; i < hits; i++) { names = *bp; bp += 3; if (*(bp + (names - 1)) == PawnName) { Pawn.state = (Pawn.state + 1) % PAWN_STATE_MAX; } else { if (Pawn.state == PAWN_STATE_SELECTED) { Pawn.row = *(bp); Pawn.column = *(bp + 1); } } bp += names; } } void stop_picking() { GLint hits; glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glFlush(); hits = glRenderMode(GL_RENDER); if (hits > 0) process_hits(hits, SelectBuffer); Mode = GL_RENDER; } // Display callback ------------------------------------------------------------ void display() { glClear(GL_COLOR_BUFFER_BIT); if (Mode == GL_SELECT) start_picking(); draw_scene(); if (Mode == GL_SELECT) stop_picking(); else glutSwapBuffers(); } // Reshape callback ------------------------------------------------------------ void reshape(GLsizei nw, GLsizei nh) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, BoardRows, 0, BoardColumns); glMatrixMode(GL_MODELVIEW); glViewport(0, 0, nw, nh); WindowWidth = nw; WindowHeight = nh; } // Mouse callback -------------------------------------------------------------- void mouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { Mode = GL_SELECT; CursorX = x; CursorY = y; } } // Passive Motion callback ------------------------------------------------------ void passive_motion(int x, int y) { CursorX = x; CursorY = y; } // Keyboard callback ------------------------------------------------------------ void keyboard(unsigned char key, int x, int y) { if (key == 'q' || key == 'Q') exit(EXIT_SUCCESS); } // Timer callback --------------------------------------------------------------- void timer(int value) { glutPostRedisplay(); glutTimerFunc(1000/FrameRate, timer, value); } // Main execution --------------------------------------------------------------- int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow("board"); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); glutPassiveMotionFunc(passive_motion); glutKeyboardFunc(keyboard); glutTimerFunc(1000/FrameRate, timer, 0); init_scene(); make_display_lists(); glutMainLoop(); return (EXIT_SUCCESS); } // vim: sts=4 sw=4 ts=8 ft=cpp