Chapter 12 Interactive Graphics Chih-Kuo Yeh
Direct Manipulation Demo
p1 COP Center of Projection p2 Window Coordinates Object 1 Object 2
Modelview Transformation Vertex Coordinates x, y, z, w Object Coordinates Eye Coordinates Clip Coordinates Device Coordinates Window Coordinates x,y Projection Transformation Perspective Division Viewport Transformation Modelview Matrix Projection Matrix Part of OpenGL State Viewport Transformation
Selection Feedback Application Model Application Program Graphics System Output Devices Input Devices API Function Calls or Protocol Data
glSelectBuffer(…) ProcessSelection glMatrixMode(GL_PROJECTION) glPushMatrix() glMatrixMode(GL_PROJECTION) glPopMatrix() Change render mode
glRenderMode(GL_SELECT ) glRenderMode(GL_RENDER ) RenderScene() gluPickMatrix(…) Change render mode
glInitNames() glPushName() glLoadName(…) RenderScene Draw your object 1 glLoadName(…) Draw your object 2
GLint glRenderMode(GLenum mode); Mode = 1. GL_RENDER (the default) 2. GL_SELECT 3. GL_FEEDBAC glRenderMode() GL_RENDER GL_SELECT 1 zmin zmax Yellow Cube glRenderMode(GL_RENDER) returns the number of hits while in SELECT mode
void gluPickMatrix(GLdouble x, GLdouble y, GLdouble width, GLdouble height, GLint viewport[4]); glGetIntegerv(GL_VIEWPORT, viewport); gluPickMatrix(xPos, viewport[3] – yPos + viewport[1], 2,2, viewport);
Perspective View Volume Canonical View Volume Projection Transform Pick Matrix Transform Screen Coordinates
Each hit record consists of four items, in order. 1. The number of names on the name stack when the hit occurred. 2. Both the minimum and maximum window-coordinate z values 3. The contents of the name stack at the time of the hit, with the bottommost element first.
void RenderScene(void) { // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Save the matrix state and do the rotations glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Translate the whole scene out and into view glTranslatef(0.0f, 0.0f, f); // Initialize the names stack glInitNames(); glPushName(0); // Name and draw the Sun glColor3f(1.0f, 1.0f, 0.0f); glLoadName(SUN); DrawSphere(15.0f); // Draw Mercury glColor3f(0.5f, 0.0f, 0.0f); glPushMatrix(); glTranslatef(24.0f, 0.0f, 0.0f); glLoadName(MERCURY); DrawSphere(2.0f); glPopMatrix(); // Draw Venus glColor3f(0.5f, 0.5f, 1.0f); glPushMatrix(); glTranslatef(60.0f, 0.0f, 0.0f); glLoadName(VENUS); DrawSphere(4.0f); glPopMatrix(); // Draw the Earth glColor3f(0.0f, 0.0f, 1.0f); glPushMatrix(); glTranslatef(100.0f,0.0f,0.0f); glLoadName(EARTH); DrawSphere(8.0f); glPopMatrix(); // Draw Mars glColor3f(1.0f, 0.0f, 0.0f); glPushMatrix(); glTranslatef(150.0f, 0.0f, 0.0f); glLoadName(MARS); DrawSphere(4.0f); glPopMatrix(); // Restore the matrix state glPopMatrix();// Modelview matrix glutSwapBuffers(); }
void MouseCallback(int button, int state, int x, int y) { if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) ProcessSelection(x, y); }
void ProcessSelection(int xPos, int yPos) { GLfloat fAspect; // Space for selection buffer static GLuint selectBuff[BUFFER_LENGTH]; // Hit counter and viewport storage GLint hits, viewport[4]; // Setup selection buffer glSelectBuffer(BUFFER_LENGTH, selectBuff);
// Get the viewport glGetIntegerv(GL_VIEWPORT, viewport); // Switch to projection and save the matrix glMatrixMode(GL_PROJECTION); glPushMatrix(); // Change render mode glRenderMode(GL_SELECT);
glLoadIdentity(); gluPickMatrix(xPos, viewport[3] - yPos + viewport[1], 2,2, viewport); // Apply perspective matrix fAspect = (float)viewport[2] / (float)viewport[3]; gluPerspective(45.0f, fAspect, 1.0, 425.0); // Draw the scene RenderScene(); // Collect the hits hits = glRenderMode(GL_RENDER);
GLuint nErr = glGetError(); // If a single hit occurred, display the info. if(hits == 1) ProcessPlanet(selectBuff[3]); else glutSetWindowTitle("Nothing was clicked on!"); // Restore the projection matrix glMatrixMode(GL_PROJECTION); glPopMatrix(); // Go back to modelview for normal rendering glMatrixMode(GL_MODELVIEW);
glSelectBuffer( int size, int *pBuffer ); Set up Pick Buffer Selection Buffer: user specified integer array
stack pointer Set up Pick Buffer Initialize Name Stack glRenderMode( GL_SELECT ); glInitNames();
gluPickMatrix( x, y, 5.0, 5.0, viewport ); Initialize Name Stack Set up Pick Buffer Specify a Pick Volume
glPushName(100); Specify a Pick Volume Initialize Name Stack Set up Pick Buffer Draw Object with IDs glDrawRedRect();
glPushName(200); Specify a Pick Volume Draw Object with IDs Initialize Name Stack Set up Pick Buffer glDrawGreenRect();
Specify a Pick Volume Draw Object with IDs Initialize Name Stack Set up Pick Buffer glPushName(300); glDrawBlueRect();
Do anything you want !!! Specify a Pick Volume Draw Object with IDs Initialize Name Stack Set up Pick Buffer Post Processing gRenderMode( GL_RENDER );
glSelectBuffer(…) ProcessSelection glMatrixMode(GL_PROJECTION) glPushMatrix() glMatrixMode(GL_PROJECTION) glPopMatrix() Change render mode MakeSelection
glRenderMode(GL_SELECT ) glRenderMode(GL_RENDER ) RenderScene() gluPickMatrix(…) Change render mode
glInitNames() glPushName() RenderScene glLoadName(…) Draw your object 1 glPassThrough(…) glLoadName(…) Draw your object 2 glPassThrough(…)
glRenderMode(GL_FEEDBACK ) glRenderMode(GL_RENDER ) RenderScene() glFeedbackBuffer(…) MakeSelection Parse the feedback buffer
void glFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer);
GL_3D type
[0] GL_PASS_THROUGH_TOKEN [1] User defined name [2] GL_POLYGON_TOKEN [3] Number of vertices [4] x [5] y See MakeSelection(int nChoice) for detail