110 likes | 124 Views
Learn how to implement object picking in 3D scenes using two approaches - ID-Buffer and Selection Mode - in OpenGL for user-friendly interactions.
E N D
Picking in OpenGL • Yingcai Xiao
Picking • Identifying objects in 3D • Two approaches • HW: ID-Buffer • SW: Selection Mode
HW: ID-Buffer • Use a memory buffer of the same resolution as the frame buffer. • Assign each object an ID (name) • Update the ID buffer with the object ID whenever the frame buffer is being updated (after checking and updating the z-buffer) • Return the ID at the cursor location when the user clicks the left button
SW: Selection Mode • Same idea as the ID-buffer but without using the buffer. • Switch render mode to the selection mode • Set a small picking area around the cursor (e.g. 5x5) as the viewport • “Render” each object after pushing its name on the stack • All objects in the small viewport are added into a hit-list. • The ID, zmin and zmax of each hit-object are stored into a predefined selection buffer not • Switch back to regular render mode • Process the hit-list (e.g. display the selected object with highlight)
Implement picking in OpenGL gluPickMatrix(x, y, width, height, viewport); x, y should be set as the mouse location: xMouse and yMouse width, height are the size of the picking box glGetIntegerv(GL_VIEWPORT, viewport); glInitNames(); glPushName(ID);
Example 1: void pick(xPos, yPos) { glSelectBuffer(LENGTH, selectBuff); glRenderMode(GL_SELECTION); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPickMatrix(x, y, 2, 2, viewport); gluPerspective(fovy, aspect, near, far); RenderScene(); hits = glRenderMode(GL_RENDER); Cout << we pick << selectBuff[3] << object; }
Example 2: void ObjectManager::selectObject(float x, float y) { GLuint buff[64] = {0}; GLint hits, view[4]; glSelectBuffer(64, buff); glGetIntegerv(GL_VIEWPORT, view); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix(x, y, 0.05,0.05 , view); gluOrtho2D(0, 800, 0, 600);
Example 2: glutSwapBuffers(); drawObjects(); glMatrixMode(GL_PROJECTION); glPopMatrix(); hits = glRenderMode(GL_RENDER); list_hits(hits, buff); glMatrixMode(GL_MODELVIEW); }
Example 2: void ObjectManager::drawObjects() { for (list<GameObject*>::iterator ii = Objects.begin(); ii != Objects.end(); ++ii) { glLoadName((*ii)->getId()); glPushMatrix(); (*ii)->drawObject(); glPopMatrix(); } }
Example 2: void ObjectManager::list_hits(GLint hits, GLuint *names) { for (int i = 0;i<hits;i++) { for (list<GameObject*>::iterator ii = Objects.begin(); ii != Objects.end(); ++ii) { if ((GLubyte)names[i * 4 + 3] == (*ii)->getId()) (*ii)->onMouse(); } }
Example 2: printf("%d hits:\n", hits); for (i = 0; i < hits; i++) printf( "Number: %d\n" "Min Z: %d\n" "Max Z: %d\n" "Name on stack: %d\n", (GLubyte)names[i * 4], (GLubyte)names[i * 4 + 1], (GLubyte)names[i * 4 + 2], (GLubyte)names[i * 4 + 3] ); printf("\n"); }