/* * ThreePicks.cpp * Picks and animates objects - this program illustrates how to pick objects on the screen and * animate them in response. * Three different methods of picking are illustrated: * Bounding box, distance to center, frame buffer contents * * Also illustrates/compares two methods of animating a wheel * * Created on: Mar 1, 2013 * Author: debure */ #include #include #include #include #include using namespace std; GLfloat theta; bool sqStart = false, // booleans for state of each object: whStart = false, // square rotating, wheel rolling, sqGrowShrink = false; // square changing size bool grow = true; // true if growing, false if shrinking GLfloat grFactor = 50; // scale factor for growing circle GLint gsX = 100, gsY = 100; // center of growing circle GLfloat transClock = 0; // factor ranging 0 to 1 GLfloat scalefac = 50; // radius of rolling wheel GLint goX = 30, goY = 375; // center of "go" button GLfloat rsFactor = 50; // scale factor for rotating square GLint rsX = 250, rsY = 325; // center of rotating square // Color from framebuffer for third pick method GLubyte theColor[3] = { 0, 0, 0 }; // Pixel color read from framebuffer void myinit(void) { glClearColor(0.0, 0.0, 0.0, 1.0); glColor3f(0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, 500.0, 500.0, 0.0); glMatrixMode(GL_MODELVIEW); glEnableClientState(GL_VERTEX_ARRAY); } void display(void) { // square is created at the origin GLfloat sq_vertices[4][2] = { { -1.0, -1.0 }, { 1.0, -1.0 }, { 1.0, 1.0 }, { -1.0, 1.0 } }; GLubyte sqIndices[4] = { 0, 3, 2, 1 }; GLfloat ci_vertices[38][2] = { { 0, 0 }, { 1, 0 }, { 0.984808, 0.173648 }, { 0.939693, 0.34202 }, { 0.866025, 0.5 }, { 0.766044, 0.642788 }, { 0.642788, 0.766044 }, { 0.5, 0.866025 }, { 0.34202, 0.939693 }, { 0.173648, 0.984808 }, { 0, 1 }, { -0.173648, 0.984808 }, { -0.34202, 0.939693 }, { -0.5, 0.866025 }, { -0.642788, 0.766044 }, { -0.766044, 0.642788 }, { -0.866025, 0.5 }, { -0.939693, 0.34202 }, { -0.984808, 0.173648 }, { -1, 1.22461e-016 }, { -0.984808, -0.173648 }, { -0.939693, -0.34202 }, { -0.866025, -0.5 }, { -0.766044, -0.642788 }, { -0.642788, -0.766044 }, { -0.5, -0.866025 }, { -0.34202, -0.939693 }, { -0.173648, -0.984808 }, { 0, -1 }, { 0.173648, -0.984808 }, { 0.34202, -0.939693 }, { 0.5, -0.866025 }, { 0.642788, -0.766044 }, { 0.766044, -0.642788 }, { 0.866025, -0.5 }, { 0.939693, -0.34202 }, { 0.984808, -0.173648 }, { 1, 0 } }; GLubyte ciIndices[38] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 }; GLubyte whIndices[38] = { 0, 1, 0, 3, 0, 5, 0, 7, 0, 9, 0, 11, 0, 13, 0, 15, 0, 17, 0, 19, 0, 21, 0, 23, 0, 25, 0, 27, 0, 29, 0, 31, 0, 33, 0, 35, 0, 37 }; glClear(GL_COLOR_BUFFER_BIT); // code for rotating square glVertexPointer(2, GL_FLOAT, 0, sq_vertices); glColor3ub(75, 75, 255); // assign color using unsigned byte 0-255 glPushMatrix(); glLoadIdentity(); glTranslatef(rsX, rsY, 0.0); // center of rotating square glScalef(rsFactor, rsFactor, 0.0); glRotatef(theta, 0.0, 0.0, 1.0); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, sqIndices); glPopMatrix(); // code for growing circle glColor3f(0.0, 1.0, 1.0); glVertexPointer(2, GL_FLOAT, 0, ci_vertices); glPushMatrix(); glLoadIdentity(); glTranslatef(gsX, gsY, 0.0); // center of grow/shrink circle glScalef(grFactor, grFactor, 0.0); glDrawElements(GL_TRIANGLE_FAN, 38, GL_UNSIGNED_BYTE, ciIndices); glPopMatrix(); // code for rolling wheel glColor3f(1.0, 0.3, 1.0); glVertexPointer(2, GL_FLOAT, 0, ci_vertices); glPushMatrix(); glLoadIdentity(); //glTranslatef(gsX/2 + 2 * 3.14159 * scalefac*transClock, gsY+350, 0.0); // correct translation for roll glTranslatef(gsX/2 + 25 * scalefac * transClock, gsY + 350, 0.0); // irrelevant translation glScalef(scalefac, scalefac, 0.0); glRotatef(transClock * 360, 0, 0, 1); glDrawElements(GL_TRIANGLE_FAN, 38, GL_UNSIGNED_BYTE, ciIndices); glColor3f(0.0, 0.0, 0.0); glDrawElements(GL_LINES, 38, GL_UNSIGNED_BYTE, whIndices); glPopMatrix(); // code for square button to rotate wheel glVertexPointer(2, GL_FLOAT, 0, sq_vertices); glColor3f(1.0, 0.3, 1.0); glPushMatrix(); glLoadIdentity(); glTranslatef(goX, goY, 0.0); // center of square "go" button glScalef(5, 5, 0.0); glDrawElements(GL_QUADS, 4, GL_UNSIGNED_BYTE, sqIndices); glPopMatrix(); glutSwapBuffers(); glFlush(); } void idle(void) { if (sqStart) { theta += 1; // modify rotation angle that is used in display } if (whStart) { transClock += 0.0001; // modify how far wheel has moved/rotated } if (sqGrowShrink) { if (grFactor > 100) grow = false; else if (grFactor < -100) grow = true; if (grow) grFactor = grFactor + 0.05; else grFactor = grFactor - 0.05; } glutPostRedisplay(); } // readPixel - Adapted from: G. Chappell // Reads pixel at mouse position (given, GLUT format) // Puts color in theColor (global GLfloat [3]). void readPixel(int x, int y) { glReadPixels(x, 500 - y, // Read pixel at mouse position // not fb position is not affected by viewport 1, 1, // 1 x 1 block (single pixel) GL_RGB, // Get R, G, B GL_UNSIGNED_BYTE, // Return GLubyte, value 0..255 theColor); // Place to put the result } void mouse(int button, int state, int x, int y) { double dist = sqrt((gsX - x) * (gsX - x) + (gsY - y) * (gsX - y)); // compute distance from cyan circle center to mouse if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && dist < grFactor) { // check if inside growing circle sqGrowShrink = !sqGrowShrink; // using dist from center } if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && x >= goX - 5 && x <= goX + 5 && y >= goY - 5 && y <= goY + 5) { // check if inside button using bounding box whStart = !whStart; // already rotating: stop it } readPixel(x, y); if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && theColor[0] == 75 && theColor[1] == 75 && theColor[2] == 255) { // check if inside rotating square using fb read // checks if pixel is color of rotating square - blue sqStart = !sqStart; // already rotating: stop it } if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) exit(0); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(0, 0); glutCreateWindow("Pick to Go"); glutDisplayFunc(display); glutMouseFunc(mouse); glutIdleFunc(idle); myinit(); glutMainLoop(); return 0; }